@utilix-tech/sdk 0.7.0 → 0.8.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 +18 -3
- package/README.md +16 -5
- package/dist/{chunk-5CKOJXFU.js → chunk-GUUYEIU6.js} +211 -1
- package/dist/{chunk-DNCOIO5N.js → chunk-TINQFTLO.js} +19 -1
- package/dist/{data-CakDxAcT.d.cts → data-D8XTI7Du.d.cts} +21 -2
- package/dist/{data-CakDxAcT.d.ts → data-D8XTI7Du.d.ts} +21 -2
- package/dist/index.cjs +228 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{media-D66WnthC.d.cts → media-C3ZvGyKc.d.cts} +27 -2
- package/dist/{media-D66WnthC.d.ts → media-C3ZvGyKc.d.ts} +27 -2
- package/dist/tools/data.cjs +18 -0
- package/dist/tools/data.d.cts +1 -1
- package/dist/tools/data.d.ts +1 -1
- package/dist/tools/data.js +1 -1
- package/dist/tools/media.cjs +210 -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/package.json +8 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,11 +2,26 @@
|
|
|
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.
|
|
6
|
-
-
|
|
5
|
+
## 0.8.0
|
|
6
|
+
- Added ID3 Tag Reader and .env.example Diff Checker.
|
|
7
|
+
|
|
8
|
+
## 0.7.0
|
|
9
|
+
- Added WAV Audio Info and Readability Score Calculator.
|
|
10
|
+
|
|
11
|
+
## 0.6.0
|
|
12
|
+
- Added EXIF Viewer and Commit Message Generator (AI).
|
|
13
|
+
|
|
14
|
+
## 0.5.0
|
|
15
|
+
- Added PDF Metadata Reader and JWK Viewer.
|
|
16
|
+
|
|
17
|
+
## 0.4.1
|
|
18
|
+
- Added HAR File Viewer and NDJSON Formatter/Validator.
|
|
19
|
+
|
|
20
|
+
## 0.4.0
|
|
21
|
+
- Metadata fixes: corrected repository/bug tracker links, updated the stale dependency, added missing package files.
|
|
7
22
|
|
|
8
23
|
## 0.3.0
|
|
9
|
-
- Added the `media` module.
|
|
24
|
+
- Added the `media` module (Passive Voice Detector, Image Info).
|
|
10
25
|
|
|
11
26
|
## 0.2.0
|
|
12
27
|
- 400+ functions across 14 modules, including the `ai_agent` module for LLM/RAG pipelines.
|
package/README.md
CHANGED
|
@@ -156,12 +156,12 @@ scoreReadability("The cat sat on the mat. It was a sunny day.");
|
|
|
156
156
|
|
|
157
157
|
---
|
|
158
158
|
|
|
159
|
-
### `/data`: CSV / YAML / TOML / XML / INI / NDJSON
|
|
159
|
+
### `/data`: CSV / YAML / TOML / XML / INI / NDJSON / .env diff
|
|
160
160
|
|
|
161
161
|
```ts
|
|
162
162
|
import { parseCsv, csvToJson, validateYaml, tomlToJson, jsonToToml,
|
|
163
163
|
formatXml, xmlToJson, jsonToXml, parseIni,
|
|
164
|
-
validateNdjson, formatNdjson, ndjsonToJsonArray } from "@utilix-tech/sdk/data";
|
|
164
|
+
validateNdjson, formatNdjson, ndjsonToJsonArray, diffEnvExample } from "@utilix-tech/sdk/data";
|
|
165
165
|
|
|
166
166
|
// CSV
|
|
167
167
|
const rows = parseCsv("name,age\nalice,30\nbob,25");
|
|
@@ -185,6 +185,10 @@ parseIni("[db]\nhost=localhost\nport=5432");
|
|
|
185
185
|
validateNdjson('{"id":1}\n{"id":2}'); // { valid: true, totalLines: 2, ... }
|
|
186
186
|
formatNdjson('{"id":1}'); // '{\n "id": 1\n}'
|
|
187
187
|
ndjsonToJsonArray('{"id":1}\n{"id":2}'); // '[\n { "id": 1 },\n { "id": 2 }\n]'
|
|
188
|
+
|
|
189
|
+
// Diff a .env file against its .env.example template
|
|
190
|
+
diffEnvExample("FOO=1\nBAR=2", "FOO=\nBAR=y\nBAZ=z");
|
|
191
|
+
// { missingInExample: [], missingInEnv: ["BAZ"], emptyValueInExample: ["FOO"], keysInBoth: 2 }
|
|
188
192
|
```
|
|
189
193
|
|
|
190
194
|
---
|
|
@@ -420,10 +424,10 @@ analyzeString("café"); // { length: 4, codePoints: [...], ... }
|
|
|
420
424
|
|
|
421
425
|
---
|
|
422
426
|
|
|
423
|
-
### `/media`: Image Header Parsing, EXIF, PDF &
|
|
427
|
+
### `/media`: Image Header Parsing, EXIF, PDF, WAV & ID3 Metadata
|
|
424
428
|
|
|
425
429
|
```ts
|
|
426
|
-
import { readImageInfo, readExifData, readPdfMetadata, readWavInfo } from "@utilix-tech/sdk/media";
|
|
430
|
+
import { readImageInfo, readExifData, readPdfMetadata, readWavInfo, readId3Tags } from "@utilix-tech/sdk/media";
|
|
427
431
|
|
|
428
432
|
// Reads format, dimensions, bit depth, and alpha channel straight from
|
|
429
433
|
// file bytes: no decoding, no canvas, no image library.
|
|
@@ -448,9 +452,16 @@ readPdfMetadata(new Uint8Array(pdfBytes));
|
|
|
448
452
|
const wavBytes = await fs.promises.readFile("recording.wav");
|
|
449
453
|
readWavInfo(new Uint8Array(wavBytes));
|
|
450
454
|
// { audioFormat: 1, audioFormatLabel: "PCM", channels: 2, sampleRate: 44100, bitsPerSample: 16, durationSeconds: 12.4, ... }
|
|
455
|
+
|
|
456
|
+
// Reads title, artist, album, year, genre, comment, and track number from
|
|
457
|
+
// an MP3's ID3 tags. Prefers ID3v2.3/2.4 text frames, falls back to the
|
|
458
|
+
// classic 128-byte ID3v1/1.1 trailer.
|
|
459
|
+
const mp3Bytes = await fs.promises.readFile("track.mp3");
|
|
460
|
+
readId3Tags(new Uint8Array(mp3Bytes));
|
|
461
|
+
// { version: "ID3v2.3.0", title: "Track Name", artist: "Artist Name", genre: "Rock", ... }
|
|
451
462
|
```
|
|
452
463
|
|
|
453
|
-
`readImageInfo` supports PNG, JPEG, GIF, WebP, and BMP. `readExifData` supports JPEG only. `readWavInfo` supports the canonical RIFF/WAVE container only.
|
|
464
|
+
`readImageInfo` supports PNG, JPEG, GIF, WebP, and BMP. `readExifData` supports JPEG only. `readWavInfo` supports the canonical RIFF/WAVE container only. `readId3Tags` decodes ID3v2.3/2.4 and ID3v1/1.1 only (ID3v2.2 is detected but not decoded).
|
|
454
465
|
|
|
455
466
|
---
|
|
456
467
|
|
|
@@ -4,6 +4,7 @@ import { __export } from './chunk-MLKGABMK.js';
|
|
|
4
4
|
var media_exports = {};
|
|
5
5
|
__export(media_exports, {
|
|
6
6
|
readExifData: () => readExifData,
|
|
7
|
+
readId3Tags: () => readId3Tags,
|
|
7
8
|
readImageInfo: () => readImageInfo,
|
|
8
9
|
readPdfMetadata: () => readPdfMetadata,
|
|
9
10
|
readWavInfo: () => readWavInfo
|
|
@@ -520,5 +521,214 @@ function readWavInfo(bytes) {
|
|
|
520
521
|
fileSize
|
|
521
522
|
};
|
|
522
523
|
}
|
|
524
|
+
var ID3V1_GENRES = [
|
|
525
|
+
"Blues",
|
|
526
|
+
"Classic Rock",
|
|
527
|
+
"Country",
|
|
528
|
+
"Dance",
|
|
529
|
+
"Disco",
|
|
530
|
+
"Funk",
|
|
531
|
+
"Grunge",
|
|
532
|
+
"Hip-Hop",
|
|
533
|
+
"Jazz",
|
|
534
|
+
"Metal",
|
|
535
|
+
"New Age",
|
|
536
|
+
"Oldies",
|
|
537
|
+
"Other",
|
|
538
|
+
"Pop",
|
|
539
|
+
"R&B",
|
|
540
|
+
"Rap",
|
|
541
|
+
"Reggae",
|
|
542
|
+
"Rock",
|
|
543
|
+
"Techno",
|
|
544
|
+
"Industrial",
|
|
545
|
+
"Alternative",
|
|
546
|
+
"Ska",
|
|
547
|
+
"Death Metal",
|
|
548
|
+
"Pranks",
|
|
549
|
+
"Soundtrack",
|
|
550
|
+
"Euro-Techno",
|
|
551
|
+
"Ambient",
|
|
552
|
+
"Trip-Hop",
|
|
553
|
+
"Vocal",
|
|
554
|
+
"Jazz+Funk",
|
|
555
|
+
"Fusion",
|
|
556
|
+
"Trance",
|
|
557
|
+
"Classical",
|
|
558
|
+
"Instrumental",
|
|
559
|
+
"Acid",
|
|
560
|
+
"House",
|
|
561
|
+
"Game",
|
|
562
|
+
"Sound Clip",
|
|
563
|
+
"Gospel",
|
|
564
|
+
"Noise",
|
|
565
|
+
"AlternRock",
|
|
566
|
+
"Bass",
|
|
567
|
+
"Soul",
|
|
568
|
+
"Punk",
|
|
569
|
+
"Space",
|
|
570
|
+
"Meditative",
|
|
571
|
+
"Instrumental Pop",
|
|
572
|
+
"Instrumental Rock",
|
|
573
|
+
"Ethnic",
|
|
574
|
+
"Gothic",
|
|
575
|
+
"Darkwave",
|
|
576
|
+
"Techno-Industrial",
|
|
577
|
+
"Electronic",
|
|
578
|
+
"Pop-Folk",
|
|
579
|
+
"Eurodance",
|
|
580
|
+
"Dream",
|
|
581
|
+
"Southern Rock",
|
|
582
|
+
"Comedy",
|
|
583
|
+
"Cult",
|
|
584
|
+
"Gangsta",
|
|
585
|
+
"Top 40",
|
|
586
|
+
"Christian Rap",
|
|
587
|
+
"Pop/Funk",
|
|
588
|
+
"Jungle",
|
|
589
|
+
"Native American",
|
|
590
|
+
"Cabaret",
|
|
591
|
+
"New Wave",
|
|
592
|
+
"Psychedelic",
|
|
593
|
+
"Rave",
|
|
594
|
+
"Showtunes",
|
|
595
|
+
"Trailer",
|
|
596
|
+
"Lo-Fi",
|
|
597
|
+
"Tribal",
|
|
598
|
+
"Acid Punk",
|
|
599
|
+
"Acid Jazz",
|
|
600
|
+
"Polka",
|
|
601
|
+
"Retro",
|
|
602
|
+
"Musical",
|
|
603
|
+
"Rock & Roll",
|
|
604
|
+
"Hard Rock"
|
|
605
|
+
];
|
|
606
|
+
function readSynchsafeUInt32(bytes, offset) {
|
|
607
|
+
return (bytes[offset] & 127) << 21 | (bytes[offset + 1] & 127) << 14 | (bytes[offset + 2] & 127) << 7 | bytes[offset + 3] & 127;
|
|
608
|
+
}
|
|
609
|
+
function readUInt32BE(bytes, offset) {
|
|
610
|
+
return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
|
|
611
|
+
}
|
|
612
|
+
function decodeId3Text(frameBytes) {
|
|
613
|
+
if (frameBytes.length === 0) return "";
|
|
614
|
+
const encodingByte = frameBytes[0];
|
|
615
|
+
const content = frameBytes.subarray(1);
|
|
616
|
+
let out = "";
|
|
617
|
+
if (encodingByte === 3) {
|
|
618
|
+
out = Buffer.from(content).toString("utf8");
|
|
619
|
+
} else if (encodingByte === 1 || encodingByte === 2) {
|
|
620
|
+
let little = encodingByte === 1;
|
|
621
|
+
let start = 0;
|
|
622
|
+
if (encodingByte === 1 && content.length >= 2) {
|
|
623
|
+
if (content[0] === 255 && content[1] === 254) {
|
|
624
|
+
little = true;
|
|
625
|
+
start = 2;
|
|
626
|
+
} else if (content[0] === 254 && content[1] === 255) {
|
|
627
|
+
little = false;
|
|
628
|
+
start = 2;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
for (let i = start; i + 1 < content.length; i += 2) {
|
|
632
|
+
const code = little ? content[i] | content[i + 1] << 8 : content[i] << 8 | content[i + 1];
|
|
633
|
+
if (code === 0) break;
|
|
634
|
+
out += String.fromCharCode(code);
|
|
635
|
+
}
|
|
636
|
+
} else {
|
|
637
|
+
for (const b of content) {
|
|
638
|
+
if (b === 0) break;
|
|
639
|
+
out += String.fromCharCode(b);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
return out.replace(/\0+$/, "").trim();
|
|
643
|
+
}
|
|
644
|
+
function readId3v2(bytes) {
|
|
645
|
+
if (bytes.length < 10 || bytes[0] !== 73 || bytes[1] !== 68 || bytes[2] !== 51) return null;
|
|
646
|
+
const majorVersion = bytes[3];
|
|
647
|
+
const revision = bytes[4];
|
|
648
|
+
const tagSize = readSynchsafeUInt32(bytes, 6);
|
|
649
|
+
const version = `ID3v2.${majorVersion}.${revision}`;
|
|
650
|
+
if (majorVersion !== 3 && majorVersion !== 4) {
|
|
651
|
+
return { version, frames: {}, frameCount: 0 };
|
|
652
|
+
}
|
|
653
|
+
const frames = {};
|
|
654
|
+
let offset = 10;
|
|
655
|
+
const end = Math.min(10 + tagSize, bytes.length);
|
|
656
|
+
let frameCount = 0;
|
|
657
|
+
while (offset + 10 <= end) {
|
|
658
|
+
const frameId = String.fromCharCode(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]);
|
|
659
|
+
if (frameId === "\0\0\0\0") break;
|
|
660
|
+
const frameSize = majorVersion === 4 ? readSynchsafeUInt32(bytes, offset + 4) : readUInt32BE(bytes, offset + 4);
|
|
661
|
+
const frameStart = offset + 10;
|
|
662
|
+
if (frameSize <= 0 || frameStart + frameSize > bytes.length) break;
|
|
663
|
+
const frameBytes = bytes.subarray(frameStart, frameStart + frameSize);
|
|
664
|
+
if (frameId[0] === "T" && frameId !== "TXXX") {
|
|
665
|
+
frames[frameId] = decodeId3Text(frameBytes);
|
|
666
|
+
} else if (frameId === "COMM" && frameBytes.length > 4) {
|
|
667
|
+
const rebuilt = new Uint8Array(frameBytes.length - 3);
|
|
668
|
+
rebuilt[0] = frameBytes[0];
|
|
669
|
+
rebuilt.set(frameBytes.subarray(4), 1);
|
|
670
|
+
const decoded = decodeId3Text(rebuilt);
|
|
671
|
+
const parts = decoded.split("\0");
|
|
672
|
+
frames["COMM"] = (parts[parts.length - 1] || decoded).trim();
|
|
673
|
+
}
|
|
674
|
+
frameCount++;
|
|
675
|
+
offset = frameStart + frameSize;
|
|
676
|
+
}
|
|
677
|
+
return { version, frames, frameCount };
|
|
678
|
+
}
|
|
679
|
+
function readId3v1(bytes) {
|
|
680
|
+
if (bytes.length < 128) return null;
|
|
681
|
+
const start = bytes.length - 128;
|
|
682
|
+
if (String.fromCharCode(bytes[start], bytes[start + 1], bytes[start + 2]) !== "TAG") return null;
|
|
683
|
+
const readField = (offset, length) => {
|
|
684
|
+
let s = "";
|
|
685
|
+
for (let i = 0; i < length; i++) {
|
|
686
|
+
const b = bytes[start + offset + i];
|
|
687
|
+
if (b === 0) break;
|
|
688
|
+
s += String.fromCharCode(b);
|
|
689
|
+
}
|
|
690
|
+
return s.trim();
|
|
691
|
+
};
|
|
692
|
+
const title = readField(3, 30);
|
|
693
|
+
const artist = readField(33, 30);
|
|
694
|
+
const album = readField(63, 30);
|
|
695
|
+
const year = readField(93, 4);
|
|
696
|
+
const isV11 = bytes[start + 125] === 0 && bytes[start + 126] !== 0;
|
|
697
|
+
const comment = readField(97, isV11 ? 28 : 30);
|
|
698
|
+
const genreIndex = bytes[start + 127];
|
|
699
|
+
const genre = ID3V1_GENRES[genreIndex] ?? `Unknown (${genreIndex})`;
|
|
700
|
+
const result = { genre };
|
|
701
|
+
if (title) result.title = title;
|
|
702
|
+
if (artist) result.artist = artist;
|
|
703
|
+
if (album) result.album = album;
|
|
704
|
+
if (year) result.year = year;
|
|
705
|
+
if (comment) result.comment = comment;
|
|
706
|
+
if (isV11) result.trackNumber = String(bytes[start + 126]);
|
|
707
|
+
return result;
|
|
708
|
+
}
|
|
709
|
+
function readId3Tags(bytes) {
|
|
710
|
+
const v2 = readId3v2(bytes);
|
|
711
|
+
const v1 = readId3v1(bytes);
|
|
712
|
+
if (v2 && Object.keys(v2.frames).length > 0) {
|
|
713
|
+
const f = v2.frames;
|
|
714
|
+
const result = { version: v2.version, frameCount: v2.frameCount };
|
|
715
|
+
if (f["TIT2"]) result.title = f["TIT2"];
|
|
716
|
+
if (f["TPE1"]) result.artist = f["TPE1"];
|
|
717
|
+
if (f["TALB"]) result.album = f["TALB"];
|
|
718
|
+
const year = f["TYER"] || f["TDRC"];
|
|
719
|
+
if (year) result.year = year;
|
|
720
|
+
if (f["TCON"]) result.genre = f["TCON"];
|
|
721
|
+
if (f["COMM"]) result.comment = f["COMM"];
|
|
722
|
+
if (f["TRCK"]) result.trackNumber = f["TRCK"];
|
|
723
|
+
return result;
|
|
724
|
+
}
|
|
725
|
+
if (v1) {
|
|
726
|
+
return { version: v1.trackNumber !== void 0 ? "ID3v1.1" : "ID3v1", ...v1 };
|
|
727
|
+
}
|
|
728
|
+
if (v2) {
|
|
729
|
+
return { error: `Unsupported ID3 tag version: ${v2.version} (only ID3v2.3, ID3v2.4, and ID3v1/1.1 are supported)` };
|
|
730
|
+
}
|
|
731
|
+
return { error: "No ID3v1 or ID3v2.3/2.4 tags found in this file" };
|
|
732
|
+
}
|
|
523
733
|
|
|
524
|
-
export { media_exports, readExifData, readImageInfo, readPdfMetadata, readWavInfo };
|
|
734
|
+
export { media_exports, readExifData, readId3Tags, readImageInfo, readPdfMetadata, readWavInfo };
|
|
@@ -7,6 +7,7 @@ var data_exports = {};
|
|
|
7
7
|
__export(data_exports, {
|
|
8
8
|
csvToJson: () => csvToJson,
|
|
9
9
|
detectDelimiter: () => detectDelimiter,
|
|
10
|
+
diffEnvExample: () => diffEnvExample,
|
|
10
11
|
envToExport: () => envToExport,
|
|
11
12
|
envToJson: () => envToJson,
|
|
12
13
|
formatNdjson: () => formatNdjson,
|
|
@@ -1081,6 +1082,23 @@ function envToExport(input) {
|
|
|
1081
1082
|
function validateEnvKey(key) {
|
|
1082
1083
|
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key);
|
|
1083
1084
|
}
|
|
1085
|
+
function diffEnvExample(envInput, exampleInput) {
|
|
1086
|
+
const envParsed = parseEnv(envInput);
|
|
1087
|
+
if (envParsed.errors.length > 0) {
|
|
1088
|
+
return { error: `.env: ${envParsed.errors.map((e) => `Line ${e.line}: ${e.message}`).join("; ")}` };
|
|
1089
|
+
}
|
|
1090
|
+
const exampleParsed = parseEnv(exampleInput);
|
|
1091
|
+
if (exampleParsed.errors.length > 0) {
|
|
1092
|
+
return { error: `.env.example: ${exampleParsed.errors.map((e) => `Line ${e.line}: ${e.message}`).join("; ")}` };
|
|
1093
|
+
}
|
|
1094
|
+
const envKeys = new Set(envParsed.entries.map((e) => e.key));
|
|
1095
|
+
const exampleValues = new Map(exampleParsed.entries.map((e) => [e.key, e.value]));
|
|
1096
|
+
const missingInExample = [...envKeys].filter((k) => !exampleValues.has(k)).sort();
|
|
1097
|
+
const missingInEnv = [...exampleValues.keys()].filter((k) => !envKeys.has(k)).sort();
|
|
1098
|
+
const emptyValueInExample = [...exampleValues.entries()].filter(([k, v]) => envKeys.has(k) && v === "").map(([k]) => k).sort();
|
|
1099
|
+
const keysInBoth = [...envKeys].filter((k) => exampleValues.has(k)).length;
|
|
1100
|
+
return { missingInExample, missingInEnv, emptyValueInExample, keysInBoth };
|
|
1101
|
+
}
|
|
1084
1102
|
function validateNdjson(input) {
|
|
1085
1103
|
const rawLines = input.split("\n");
|
|
1086
1104
|
const lines = [];
|
|
@@ -1140,4 +1158,4 @@ function jsonArrayToNdjson(input) {
|
|
|
1140
1158
|
return parsed.map((item) => JSON.stringify(item)).join("\n");
|
|
1141
1159
|
}
|
|
1142
1160
|
|
|
1143
|
-
export { csvToJson, data_exports, detectDelimiter, envToExport, envToJson, formatNdjson, formatToml, formatXml, getSection, getSectionNames, getTomlStats, getXmlStats, getYamlStats, iniToJson, jsonArrayToNdjson, jsonToIni, jsonToToml, jsonToXml, minifyNdjson, minifyToml, minifyXml, ndjsonToJsonArray, parseCsv, parseEnv, parseIni, parseXmlToObject, stringifyIni, toCsvString, tomlToJson, validateEnvKey, validateIni, validateNdjson, validateToml, validateXml, validateYaml, xmlToJson };
|
|
1161
|
+
export { csvToJson, data_exports, detectDelimiter, diffEnvExample, envToExport, envToJson, formatNdjson, formatToml, formatXml, getSection, getSectionNames, getTomlStats, getXmlStats, getYamlStats, iniToJson, jsonArrayToNdjson, jsonToIni, jsonToToml, jsonToXml, minifyNdjson, minifyToml, minifyXml, ndjsonToJsonArray, parseCsv, parseEnv, parseIni, parseXmlToObject, stringifyIni, toCsvString, tomlToJson, validateEnvKey, validateIni, validateNdjson, validateToml, validateXml, validateYaml, xmlToJson };
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - csv-viewer : detectDelimiter, parseCsv, csvToJson, toCsvString
|
|
11
11
|
* - ini-parser : parseIni, stringifyIni, iniToJson, jsonToIni, getSection, getSectionNames, validateIni
|
|
12
12
|
* - env-parser : parseEnv, envToJson, envToExport, validateEnvKey
|
|
13
|
+
* - env-diff-checker: diffEnvExample
|
|
13
14
|
* - ndjson-formatter: validateNdjson, minifyNdjson, formatNdjson, ndjsonToJsonArray, jsonArrayToNdjson
|
|
14
15
|
*/
|
|
15
16
|
interface ValidationResult {
|
|
@@ -168,6 +169,21 @@ declare function envToJson(input: string): string | {
|
|
|
168
169
|
};
|
|
169
170
|
declare function envToExport(input: string): string;
|
|
170
171
|
declare function validateEnvKey(key: string): boolean;
|
|
172
|
+
interface EnvDiffResult {
|
|
173
|
+
missingInExample: string[];
|
|
174
|
+
missingInEnv: string[];
|
|
175
|
+
emptyValueInExample: string[];
|
|
176
|
+
keysInBoth: number;
|
|
177
|
+
}
|
|
178
|
+
interface EnvDiffError {
|
|
179
|
+
error: string;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Diff a .env file against its .env.example template. Flags keys present in
|
|
183
|
+
* one file but not the other, plus keys that exist in both but whose
|
|
184
|
+
* .env.example value is an empty placeholder (i.e. undocumented default).
|
|
185
|
+
*/
|
|
186
|
+
declare function diffEnvExample(envInput: string, exampleInput: string): EnvDiffResult | EnvDiffError;
|
|
171
187
|
interface NdjsonLineResult {
|
|
172
188
|
line: number;
|
|
173
189
|
raw: string;
|
|
@@ -196,6 +212,8 @@ declare function jsonArrayToNdjson(input: string): string | {
|
|
|
196
212
|
};
|
|
197
213
|
|
|
198
214
|
type data_CsvParseResult = CsvParseResult;
|
|
215
|
+
type data_EnvDiffError = EnvDiffError;
|
|
216
|
+
type data_EnvDiffResult = EnvDiffResult;
|
|
199
217
|
type data_EnvEntry = EnvEntry;
|
|
200
218
|
type data_EnvParseResult = EnvParseResult;
|
|
201
219
|
type data_IniSection = IniSection;
|
|
@@ -209,6 +227,7 @@ type data_XmlFormatResult = XmlFormatResult;
|
|
|
209
227
|
type data_XmlToJsonOptions = XmlToJsonOptions;
|
|
210
228
|
declare const data_csvToJson: typeof csvToJson;
|
|
211
229
|
declare const data_detectDelimiter: typeof detectDelimiter;
|
|
230
|
+
declare const data_diffEnvExample: typeof diffEnvExample;
|
|
212
231
|
declare const data_envToExport: typeof envToExport;
|
|
213
232
|
declare const data_envToJson: typeof envToJson;
|
|
214
233
|
declare const data_formatNdjson: typeof formatNdjson;
|
|
@@ -243,7 +262,7 @@ declare const data_validateXml: typeof validateXml;
|
|
|
243
262
|
declare const data_validateYaml: typeof validateYaml;
|
|
244
263
|
declare const data_xmlToJson: typeof xmlToJson;
|
|
245
264
|
declare namespace data {
|
|
246
|
-
export { type data_CsvParseResult as CsvParseResult, type data_EnvEntry as EnvEntry, type data_EnvParseResult as EnvParseResult, type data_IniSection as IniSection, type data_NdjsonLineResult as NdjsonLineResult, type data_NdjsonValidateResult as NdjsonValidateResult, type data_ParseOptions as ParseOptions, type data_ParsedIni as ParsedIni, type data_TomlFormatResult as TomlFormatResult, type data_ValidationResult as ValidationResult, type data_XmlFormatResult as XmlFormatResult, type data_XmlToJsonOptions as XmlToJsonOptions, data_csvToJson as csvToJson, data_detectDelimiter as detectDelimiter, data_envToExport as envToExport, data_envToJson as envToJson, data_formatNdjson as formatNdjson, data_formatToml as formatToml, data_formatXml as formatXml, data_getSection as getSection, data_getSectionNames as getSectionNames, data_getTomlStats as getTomlStats, data_getXmlStats as getXmlStats, data_getYamlStats as getYamlStats, data_iniToJson as iniToJson, data_jsonArrayToNdjson as jsonArrayToNdjson, data_jsonToIni as jsonToIni, data_jsonToToml as jsonToToml, data_jsonToXml as jsonToXml, data_minifyNdjson as minifyNdjson, data_minifyToml as minifyToml, data_minifyXml as minifyXml, data_ndjsonToJsonArray as ndjsonToJsonArray, data_parseCsv as parseCsv, data_parseEnv as parseEnv, data_parseIni as parseIni, data_parseXmlToObject as parseXmlToObject, data_stringifyIni as stringifyIni, data_toCsvString as toCsvString, data_tomlToJson as tomlToJson, data_validateEnvKey as validateEnvKey, data_validateIni as validateIni, data_validateNdjson as validateNdjson, data_validateToml as validateToml, data_validateXml as validateXml, data_validateYaml as validateYaml, data_xmlToJson as xmlToJson };
|
|
265
|
+
export { type data_CsvParseResult as CsvParseResult, type data_EnvDiffError as EnvDiffError, type data_EnvDiffResult as EnvDiffResult, type data_EnvEntry as EnvEntry, type data_EnvParseResult as EnvParseResult, type data_IniSection as IniSection, type data_NdjsonLineResult as NdjsonLineResult, type data_NdjsonValidateResult as NdjsonValidateResult, type data_ParseOptions as ParseOptions, type data_ParsedIni as ParsedIni, type data_TomlFormatResult as TomlFormatResult, type data_ValidationResult as ValidationResult, type data_XmlFormatResult as XmlFormatResult, type data_XmlToJsonOptions as XmlToJsonOptions, data_csvToJson as csvToJson, data_detectDelimiter as detectDelimiter, data_diffEnvExample as diffEnvExample, data_envToExport as envToExport, data_envToJson as envToJson, data_formatNdjson as formatNdjson, data_formatToml as formatToml, data_formatXml as formatXml, data_getSection as getSection, data_getSectionNames as getSectionNames, data_getTomlStats as getTomlStats, data_getXmlStats as getXmlStats, data_getYamlStats as getYamlStats, data_iniToJson as iniToJson, data_jsonArrayToNdjson as jsonArrayToNdjson, data_jsonToIni as jsonToIni, data_jsonToToml as jsonToToml, data_jsonToXml as jsonToXml, data_minifyNdjson as minifyNdjson, data_minifyToml as minifyToml, data_minifyXml as minifyXml, data_ndjsonToJsonArray as ndjsonToJsonArray, data_parseCsv as parseCsv, data_parseEnv as parseEnv, data_parseIni as parseIni, data_parseXmlToObject as parseXmlToObject, data_stringifyIni as stringifyIni, data_toCsvString as toCsvString, data_tomlToJson as tomlToJson, data_validateEnvKey as validateEnvKey, data_validateIni as validateIni, data_validateNdjson as validateNdjson, data_validateToml as validateToml, data_validateXml as validateXml, data_validateYaml as validateYaml, data_xmlToJson as xmlToJson };
|
|
247
266
|
}
|
|
248
267
|
|
|
249
|
-
export {
|
|
268
|
+
export { minifyToml as A, minifyXml as B, type CsvParseResult as C, ndjsonToJsonArray as D, type EnvDiffError as E, parseCsv as F, parseEnv as G, parseIni as H, type IniSection as I, parseXmlToObject as J, stringifyIni as K, toCsvString as L, tomlToJson as M, type NdjsonLineResult as N, validateEnvKey as O, type ParseOptions as P, validateIni as Q, validateNdjson as R, validateToml as S, type TomlFormatResult as T, validateXml as U, type ValidationResult as V, validateYaml as W, type XmlFormatResult as X, xmlToJson as Y, type EnvDiffResult as a, type EnvEntry as b, type EnvParseResult as c, data as d, type NdjsonValidateResult as e, type ParsedIni as f, type XmlToJsonOptions as g, csvToJson as h, detectDelimiter as i, diffEnvExample as j, envToExport as k, envToJson as l, formatNdjson as m, formatToml as n, formatXml as o, getSection as p, getSectionNames as q, getTomlStats as r, getXmlStats as s, getYamlStats as t, iniToJson as u, jsonArrayToNdjson as v, jsonToIni as w, jsonToToml as x, jsonToXml as y, minifyNdjson as z };
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - csv-viewer : detectDelimiter, parseCsv, csvToJson, toCsvString
|
|
11
11
|
* - ini-parser : parseIni, stringifyIni, iniToJson, jsonToIni, getSection, getSectionNames, validateIni
|
|
12
12
|
* - env-parser : parseEnv, envToJson, envToExport, validateEnvKey
|
|
13
|
+
* - env-diff-checker: diffEnvExample
|
|
13
14
|
* - ndjson-formatter: validateNdjson, minifyNdjson, formatNdjson, ndjsonToJsonArray, jsonArrayToNdjson
|
|
14
15
|
*/
|
|
15
16
|
interface ValidationResult {
|
|
@@ -168,6 +169,21 @@ declare function envToJson(input: string): string | {
|
|
|
168
169
|
};
|
|
169
170
|
declare function envToExport(input: string): string;
|
|
170
171
|
declare function validateEnvKey(key: string): boolean;
|
|
172
|
+
interface EnvDiffResult {
|
|
173
|
+
missingInExample: string[];
|
|
174
|
+
missingInEnv: string[];
|
|
175
|
+
emptyValueInExample: string[];
|
|
176
|
+
keysInBoth: number;
|
|
177
|
+
}
|
|
178
|
+
interface EnvDiffError {
|
|
179
|
+
error: string;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Diff a .env file against its .env.example template. Flags keys present in
|
|
183
|
+
* one file but not the other, plus keys that exist in both but whose
|
|
184
|
+
* .env.example value is an empty placeholder (i.e. undocumented default).
|
|
185
|
+
*/
|
|
186
|
+
declare function diffEnvExample(envInput: string, exampleInput: string): EnvDiffResult | EnvDiffError;
|
|
171
187
|
interface NdjsonLineResult {
|
|
172
188
|
line: number;
|
|
173
189
|
raw: string;
|
|
@@ -196,6 +212,8 @@ declare function jsonArrayToNdjson(input: string): string | {
|
|
|
196
212
|
};
|
|
197
213
|
|
|
198
214
|
type data_CsvParseResult = CsvParseResult;
|
|
215
|
+
type data_EnvDiffError = EnvDiffError;
|
|
216
|
+
type data_EnvDiffResult = EnvDiffResult;
|
|
199
217
|
type data_EnvEntry = EnvEntry;
|
|
200
218
|
type data_EnvParseResult = EnvParseResult;
|
|
201
219
|
type data_IniSection = IniSection;
|
|
@@ -209,6 +227,7 @@ type data_XmlFormatResult = XmlFormatResult;
|
|
|
209
227
|
type data_XmlToJsonOptions = XmlToJsonOptions;
|
|
210
228
|
declare const data_csvToJson: typeof csvToJson;
|
|
211
229
|
declare const data_detectDelimiter: typeof detectDelimiter;
|
|
230
|
+
declare const data_diffEnvExample: typeof diffEnvExample;
|
|
212
231
|
declare const data_envToExport: typeof envToExport;
|
|
213
232
|
declare const data_envToJson: typeof envToJson;
|
|
214
233
|
declare const data_formatNdjson: typeof formatNdjson;
|
|
@@ -243,7 +262,7 @@ declare const data_validateXml: typeof validateXml;
|
|
|
243
262
|
declare const data_validateYaml: typeof validateYaml;
|
|
244
263
|
declare const data_xmlToJson: typeof xmlToJson;
|
|
245
264
|
declare namespace data {
|
|
246
|
-
export { type data_CsvParseResult as CsvParseResult, type data_EnvEntry as EnvEntry, type data_EnvParseResult as EnvParseResult, type data_IniSection as IniSection, type data_NdjsonLineResult as NdjsonLineResult, type data_NdjsonValidateResult as NdjsonValidateResult, type data_ParseOptions as ParseOptions, type data_ParsedIni as ParsedIni, type data_TomlFormatResult as TomlFormatResult, type data_ValidationResult as ValidationResult, type data_XmlFormatResult as XmlFormatResult, type data_XmlToJsonOptions as XmlToJsonOptions, data_csvToJson as csvToJson, data_detectDelimiter as detectDelimiter, data_envToExport as envToExport, data_envToJson as envToJson, data_formatNdjson as formatNdjson, data_formatToml as formatToml, data_formatXml as formatXml, data_getSection as getSection, data_getSectionNames as getSectionNames, data_getTomlStats as getTomlStats, data_getXmlStats as getXmlStats, data_getYamlStats as getYamlStats, data_iniToJson as iniToJson, data_jsonArrayToNdjson as jsonArrayToNdjson, data_jsonToIni as jsonToIni, data_jsonToToml as jsonToToml, data_jsonToXml as jsonToXml, data_minifyNdjson as minifyNdjson, data_minifyToml as minifyToml, data_minifyXml as minifyXml, data_ndjsonToJsonArray as ndjsonToJsonArray, data_parseCsv as parseCsv, data_parseEnv as parseEnv, data_parseIni as parseIni, data_parseXmlToObject as parseXmlToObject, data_stringifyIni as stringifyIni, data_toCsvString as toCsvString, data_tomlToJson as tomlToJson, data_validateEnvKey as validateEnvKey, data_validateIni as validateIni, data_validateNdjson as validateNdjson, data_validateToml as validateToml, data_validateXml as validateXml, data_validateYaml as validateYaml, data_xmlToJson as xmlToJson };
|
|
265
|
+
export { type data_CsvParseResult as CsvParseResult, type data_EnvDiffError as EnvDiffError, type data_EnvDiffResult as EnvDiffResult, type data_EnvEntry as EnvEntry, type data_EnvParseResult as EnvParseResult, type data_IniSection as IniSection, type data_NdjsonLineResult as NdjsonLineResult, type data_NdjsonValidateResult as NdjsonValidateResult, type data_ParseOptions as ParseOptions, type data_ParsedIni as ParsedIni, type data_TomlFormatResult as TomlFormatResult, type data_ValidationResult as ValidationResult, type data_XmlFormatResult as XmlFormatResult, type data_XmlToJsonOptions as XmlToJsonOptions, data_csvToJson as csvToJson, data_detectDelimiter as detectDelimiter, data_diffEnvExample as diffEnvExample, data_envToExport as envToExport, data_envToJson as envToJson, data_formatNdjson as formatNdjson, data_formatToml as formatToml, data_formatXml as formatXml, data_getSection as getSection, data_getSectionNames as getSectionNames, data_getTomlStats as getTomlStats, data_getXmlStats as getXmlStats, data_getYamlStats as getYamlStats, data_iniToJson as iniToJson, data_jsonArrayToNdjson as jsonArrayToNdjson, data_jsonToIni as jsonToIni, data_jsonToToml as jsonToToml, data_jsonToXml as jsonToXml, data_minifyNdjson as minifyNdjson, data_minifyToml as minifyToml, data_minifyXml as minifyXml, data_ndjsonToJsonArray as ndjsonToJsonArray, data_parseCsv as parseCsv, data_parseEnv as parseEnv, data_parseIni as parseIni, data_parseXmlToObject as parseXmlToObject, data_stringifyIni as stringifyIni, data_toCsvString as toCsvString, data_tomlToJson as tomlToJson, data_validateEnvKey as validateEnvKey, data_validateIni as validateIni, data_validateNdjson as validateNdjson, data_validateToml as validateToml, data_validateXml as validateXml, data_validateYaml as validateYaml, data_xmlToJson as xmlToJson };
|
|
247
266
|
}
|
|
248
267
|
|
|
249
|
-
export {
|
|
268
|
+
export { minifyToml as A, minifyXml as B, type CsvParseResult as C, ndjsonToJsonArray as D, type EnvDiffError as E, parseCsv as F, parseEnv as G, parseIni as H, type IniSection as I, parseXmlToObject as J, stringifyIni as K, toCsvString as L, tomlToJson as M, type NdjsonLineResult as N, validateEnvKey as O, type ParseOptions as P, validateIni as Q, validateNdjson as R, validateToml as S, type TomlFormatResult as T, validateXml as U, type ValidationResult as V, validateYaml as W, type XmlFormatResult as X, xmlToJson as Y, type EnvDiffResult as a, type EnvEntry as b, type EnvParseResult as c, data as d, type NdjsonValidateResult as e, type ParsedIni as f, type XmlToJsonOptions as g, csvToJson as h, detectDelimiter as i, diffEnvExample as j, envToExport as k, envToJson as l, formatNdjson as m, formatToml as n, formatXml as o, getSection as p, getSectionNames as q, getTomlStats as r, getXmlStats as s, getYamlStats as t, iniToJson as u, jsonArrayToNdjson as v, jsonToIni as w, jsonToToml as x, jsonToXml as y, minifyNdjson as z };
|
package/dist/index.cjs
CHANGED
|
@@ -4257,6 +4257,7 @@ var data_exports = {};
|
|
|
4257
4257
|
__export(data_exports, {
|
|
4258
4258
|
csvToJson: () => csvToJson2,
|
|
4259
4259
|
detectDelimiter: () => detectDelimiter2,
|
|
4260
|
+
diffEnvExample: () => diffEnvExample,
|
|
4260
4261
|
envToExport: () => envToExport,
|
|
4261
4262
|
envToJson: () => envToJson,
|
|
4262
4263
|
formatNdjson: () => formatNdjson,
|
|
@@ -5331,6 +5332,23 @@ function envToExport(input) {
|
|
|
5331
5332
|
function validateEnvKey(key) {
|
|
5332
5333
|
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key);
|
|
5333
5334
|
}
|
|
5335
|
+
function diffEnvExample(envInput, exampleInput) {
|
|
5336
|
+
const envParsed = parseEnv(envInput);
|
|
5337
|
+
if (envParsed.errors.length > 0) {
|
|
5338
|
+
return { error: `.env: ${envParsed.errors.map((e) => `Line ${e.line}: ${e.message}`).join("; ")}` };
|
|
5339
|
+
}
|
|
5340
|
+
const exampleParsed = parseEnv(exampleInput);
|
|
5341
|
+
if (exampleParsed.errors.length > 0) {
|
|
5342
|
+
return { error: `.env.example: ${exampleParsed.errors.map((e) => `Line ${e.line}: ${e.message}`).join("; ")}` };
|
|
5343
|
+
}
|
|
5344
|
+
const envKeys = new Set(envParsed.entries.map((e) => e.key));
|
|
5345
|
+
const exampleValues = new Map(exampleParsed.entries.map((e) => [e.key, e.value]));
|
|
5346
|
+
const missingInExample = [...envKeys].filter((k) => !exampleValues.has(k)).sort();
|
|
5347
|
+
const missingInEnv = [...exampleValues.keys()].filter((k) => !envKeys.has(k)).sort();
|
|
5348
|
+
const emptyValueInExample = [...exampleValues.entries()].filter(([k, v]) => envKeys.has(k) && v === "").map(([k]) => k).sort();
|
|
5349
|
+
const keysInBoth = [...envKeys].filter((k) => exampleValues.has(k)).length;
|
|
5350
|
+
return { missingInExample, missingInEnv, emptyValueInExample, keysInBoth };
|
|
5351
|
+
}
|
|
5334
5352
|
function validateNdjson(input) {
|
|
5335
5353
|
const rawLines = input.split("\n");
|
|
5336
5354
|
const lines = [];
|
|
@@ -16997,6 +17015,7 @@ function summarizeForLlm(text, maxTokens = 200, strategy = "extractive") {
|
|
|
16997
17015
|
var media_exports = {};
|
|
16998
17016
|
__export(media_exports, {
|
|
16999
17017
|
readExifData: () => readExifData,
|
|
17018
|
+
readId3Tags: () => readId3Tags,
|
|
17000
17019
|
readImageInfo: () => readImageInfo,
|
|
17001
17020
|
readPdfMetadata: () => readPdfMetadata,
|
|
17002
17021
|
readWavInfo: () => readWavInfo
|
|
@@ -17513,6 +17532,215 @@ function readWavInfo(bytes) {
|
|
|
17513
17532
|
fileSize
|
|
17514
17533
|
};
|
|
17515
17534
|
}
|
|
17535
|
+
var ID3V1_GENRES = [
|
|
17536
|
+
"Blues",
|
|
17537
|
+
"Classic Rock",
|
|
17538
|
+
"Country",
|
|
17539
|
+
"Dance",
|
|
17540
|
+
"Disco",
|
|
17541
|
+
"Funk",
|
|
17542
|
+
"Grunge",
|
|
17543
|
+
"Hip-Hop",
|
|
17544
|
+
"Jazz",
|
|
17545
|
+
"Metal",
|
|
17546
|
+
"New Age",
|
|
17547
|
+
"Oldies",
|
|
17548
|
+
"Other",
|
|
17549
|
+
"Pop",
|
|
17550
|
+
"R&B",
|
|
17551
|
+
"Rap",
|
|
17552
|
+
"Reggae",
|
|
17553
|
+
"Rock",
|
|
17554
|
+
"Techno",
|
|
17555
|
+
"Industrial",
|
|
17556
|
+
"Alternative",
|
|
17557
|
+
"Ska",
|
|
17558
|
+
"Death Metal",
|
|
17559
|
+
"Pranks",
|
|
17560
|
+
"Soundtrack",
|
|
17561
|
+
"Euro-Techno",
|
|
17562
|
+
"Ambient",
|
|
17563
|
+
"Trip-Hop",
|
|
17564
|
+
"Vocal",
|
|
17565
|
+
"Jazz+Funk",
|
|
17566
|
+
"Fusion",
|
|
17567
|
+
"Trance",
|
|
17568
|
+
"Classical",
|
|
17569
|
+
"Instrumental",
|
|
17570
|
+
"Acid",
|
|
17571
|
+
"House",
|
|
17572
|
+
"Game",
|
|
17573
|
+
"Sound Clip",
|
|
17574
|
+
"Gospel",
|
|
17575
|
+
"Noise",
|
|
17576
|
+
"AlternRock",
|
|
17577
|
+
"Bass",
|
|
17578
|
+
"Soul",
|
|
17579
|
+
"Punk",
|
|
17580
|
+
"Space",
|
|
17581
|
+
"Meditative",
|
|
17582
|
+
"Instrumental Pop",
|
|
17583
|
+
"Instrumental Rock",
|
|
17584
|
+
"Ethnic",
|
|
17585
|
+
"Gothic",
|
|
17586
|
+
"Darkwave",
|
|
17587
|
+
"Techno-Industrial",
|
|
17588
|
+
"Electronic",
|
|
17589
|
+
"Pop-Folk",
|
|
17590
|
+
"Eurodance",
|
|
17591
|
+
"Dream",
|
|
17592
|
+
"Southern Rock",
|
|
17593
|
+
"Comedy",
|
|
17594
|
+
"Cult",
|
|
17595
|
+
"Gangsta",
|
|
17596
|
+
"Top 40",
|
|
17597
|
+
"Christian Rap",
|
|
17598
|
+
"Pop/Funk",
|
|
17599
|
+
"Jungle",
|
|
17600
|
+
"Native American",
|
|
17601
|
+
"Cabaret",
|
|
17602
|
+
"New Wave",
|
|
17603
|
+
"Psychedelic",
|
|
17604
|
+
"Rave",
|
|
17605
|
+
"Showtunes",
|
|
17606
|
+
"Trailer",
|
|
17607
|
+
"Lo-Fi",
|
|
17608
|
+
"Tribal",
|
|
17609
|
+
"Acid Punk",
|
|
17610
|
+
"Acid Jazz",
|
|
17611
|
+
"Polka",
|
|
17612
|
+
"Retro",
|
|
17613
|
+
"Musical",
|
|
17614
|
+
"Rock & Roll",
|
|
17615
|
+
"Hard Rock"
|
|
17616
|
+
];
|
|
17617
|
+
function readSynchsafeUInt32(bytes, offset) {
|
|
17618
|
+
return (bytes[offset] & 127) << 21 | (bytes[offset + 1] & 127) << 14 | (bytes[offset + 2] & 127) << 7 | bytes[offset + 3] & 127;
|
|
17619
|
+
}
|
|
17620
|
+
function readUInt32BE(bytes, offset) {
|
|
17621
|
+
return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
|
|
17622
|
+
}
|
|
17623
|
+
function decodeId3Text(frameBytes) {
|
|
17624
|
+
if (frameBytes.length === 0) return "";
|
|
17625
|
+
const encodingByte = frameBytes[0];
|
|
17626
|
+
const content = frameBytes.subarray(1);
|
|
17627
|
+
let out = "";
|
|
17628
|
+
if (encodingByte === 3) {
|
|
17629
|
+
out = Buffer.from(content).toString("utf8");
|
|
17630
|
+
} else if (encodingByte === 1 || encodingByte === 2) {
|
|
17631
|
+
let little = encodingByte === 1;
|
|
17632
|
+
let start = 0;
|
|
17633
|
+
if (encodingByte === 1 && content.length >= 2) {
|
|
17634
|
+
if (content[0] === 255 && content[1] === 254) {
|
|
17635
|
+
little = true;
|
|
17636
|
+
start = 2;
|
|
17637
|
+
} else if (content[0] === 254 && content[1] === 255) {
|
|
17638
|
+
little = false;
|
|
17639
|
+
start = 2;
|
|
17640
|
+
}
|
|
17641
|
+
}
|
|
17642
|
+
for (let i = start; i + 1 < content.length; i += 2) {
|
|
17643
|
+
const code = little ? content[i] | content[i + 1] << 8 : content[i] << 8 | content[i + 1];
|
|
17644
|
+
if (code === 0) break;
|
|
17645
|
+
out += String.fromCharCode(code);
|
|
17646
|
+
}
|
|
17647
|
+
} else {
|
|
17648
|
+
for (const b of content) {
|
|
17649
|
+
if (b === 0) break;
|
|
17650
|
+
out += String.fromCharCode(b);
|
|
17651
|
+
}
|
|
17652
|
+
}
|
|
17653
|
+
return out.replace(/\0+$/, "").trim();
|
|
17654
|
+
}
|
|
17655
|
+
function readId3v2(bytes) {
|
|
17656
|
+
if (bytes.length < 10 || bytes[0] !== 73 || bytes[1] !== 68 || bytes[2] !== 51) return null;
|
|
17657
|
+
const majorVersion = bytes[3];
|
|
17658
|
+
const revision = bytes[4];
|
|
17659
|
+
const tagSize = readSynchsafeUInt32(bytes, 6);
|
|
17660
|
+
const version2 = `ID3v2.${majorVersion}.${revision}`;
|
|
17661
|
+
if (majorVersion !== 3 && majorVersion !== 4) {
|
|
17662
|
+
return { version: version2, frames: {}, frameCount: 0 };
|
|
17663
|
+
}
|
|
17664
|
+
const frames = {};
|
|
17665
|
+
let offset = 10;
|
|
17666
|
+
const end = Math.min(10 + tagSize, bytes.length);
|
|
17667
|
+
let frameCount = 0;
|
|
17668
|
+
while (offset + 10 <= end) {
|
|
17669
|
+
const frameId = String.fromCharCode(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]);
|
|
17670
|
+
if (frameId === "\0\0\0\0") break;
|
|
17671
|
+
const frameSize = majorVersion === 4 ? readSynchsafeUInt32(bytes, offset + 4) : readUInt32BE(bytes, offset + 4);
|
|
17672
|
+
const frameStart = offset + 10;
|
|
17673
|
+
if (frameSize <= 0 || frameStart + frameSize > bytes.length) break;
|
|
17674
|
+
const frameBytes = bytes.subarray(frameStart, frameStart + frameSize);
|
|
17675
|
+
if (frameId[0] === "T" && frameId !== "TXXX") {
|
|
17676
|
+
frames[frameId] = decodeId3Text(frameBytes);
|
|
17677
|
+
} else if (frameId === "COMM" && frameBytes.length > 4) {
|
|
17678
|
+
const rebuilt = new Uint8Array(frameBytes.length - 3);
|
|
17679
|
+
rebuilt[0] = frameBytes[0];
|
|
17680
|
+
rebuilt.set(frameBytes.subarray(4), 1);
|
|
17681
|
+
const decoded = decodeId3Text(rebuilt);
|
|
17682
|
+
const parts = decoded.split("\0");
|
|
17683
|
+
frames["COMM"] = (parts[parts.length - 1] || decoded).trim();
|
|
17684
|
+
}
|
|
17685
|
+
frameCount++;
|
|
17686
|
+
offset = frameStart + frameSize;
|
|
17687
|
+
}
|
|
17688
|
+
return { version: version2, frames, frameCount };
|
|
17689
|
+
}
|
|
17690
|
+
function readId3v1(bytes) {
|
|
17691
|
+
if (bytes.length < 128) return null;
|
|
17692
|
+
const start = bytes.length - 128;
|
|
17693
|
+
if (String.fromCharCode(bytes[start], bytes[start + 1], bytes[start + 2]) !== "TAG") return null;
|
|
17694
|
+
const readField = (offset, length) => {
|
|
17695
|
+
let s = "";
|
|
17696
|
+
for (let i = 0; i < length; i++) {
|
|
17697
|
+
const b = bytes[start + offset + i];
|
|
17698
|
+
if (b === 0) break;
|
|
17699
|
+
s += String.fromCharCode(b);
|
|
17700
|
+
}
|
|
17701
|
+
return s.trim();
|
|
17702
|
+
};
|
|
17703
|
+
const title = readField(3, 30);
|
|
17704
|
+
const artist = readField(33, 30);
|
|
17705
|
+
const album = readField(63, 30);
|
|
17706
|
+
const year = readField(93, 4);
|
|
17707
|
+
const isV11 = bytes[start + 125] === 0 && bytes[start + 126] !== 0;
|
|
17708
|
+
const comment = readField(97, isV11 ? 28 : 30);
|
|
17709
|
+
const genreIndex = bytes[start + 127];
|
|
17710
|
+
const genre = ID3V1_GENRES[genreIndex] ?? `Unknown (${genreIndex})`;
|
|
17711
|
+
const result = { genre };
|
|
17712
|
+
if (title) result.title = title;
|
|
17713
|
+
if (artist) result.artist = artist;
|
|
17714
|
+
if (album) result.album = album;
|
|
17715
|
+
if (year) result.year = year;
|
|
17716
|
+
if (comment) result.comment = comment;
|
|
17717
|
+
if (isV11) result.trackNumber = String(bytes[start + 126]);
|
|
17718
|
+
return result;
|
|
17719
|
+
}
|
|
17720
|
+
function readId3Tags(bytes) {
|
|
17721
|
+
const v2 = readId3v2(bytes);
|
|
17722
|
+
const v1 = readId3v1(bytes);
|
|
17723
|
+
if (v2 && Object.keys(v2.frames).length > 0) {
|
|
17724
|
+
const f = v2.frames;
|
|
17725
|
+
const result = { version: v2.version, frameCount: v2.frameCount };
|
|
17726
|
+
if (f["TIT2"]) result.title = f["TIT2"];
|
|
17727
|
+
if (f["TPE1"]) result.artist = f["TPE1"];
|
|
17728
|
+
if (f["TALB"]) result.album = f["TALB"];
|
|
17729
|
+
const year = f["TYER"] || f["TDRC"];
|
|
17730
|
+
if (year) result.year = year;
|
|
17731
|
+
if (f["TCON"]) result.genre = f["TCON"];
|
|
17732
|
+
if (f["COMM"]) result.comment = f["COMM"];
|
|
17733
|
+
if (f["TRCK"]) result.trackNumber = f["TRCK"];
|
|
17734
|
+
return result;
|
|
17735
|
+
}
|
|
17736
|
+
if (v1) {
|
|
17737
|
+
return { version: v1.trackNumber !== void 0 ? "ID3v1.1" : "ID3v1", ...v1 };
|
|
17738
|
+
}
|
|
17739
|
+
if (v2) {
|
|
17740
|
+
return { error: `Unsupported ID3 tag version: ${v2.version} (only ID3v2.3, ID3v2.4, and ID3v1/1.1 are supported)` };
|
|
17741
|
+
}
|
|
17742
|
+
return { error: "No ID3v1 or ID3v2.3/2.4 tags found in this file" };
|
|
17743
|
+
}
|
|
17516
17744
|
|
|
17517
17745
|
// src/index.ts
|
|
17518
17746
|
var version = "0.1.0";
|
package/dist/index.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ export { j as json } from './json-BjSoIS1h.cjs';
|
|
|
2
2
|
export { e as encoding } from './encoding-7gmq-vkV.cjs';
|
|
3
3
|
export { h as hashing } from './hashing-CnetQFD_.cjs';
|
|
4
4
|
export { t as text } from './text-Bbx-tZ43.cjs';
|
|
5
|
-
export { d as data } from './data-
|
|
5
|
+
export { d as data } from './data-D8XTI7Du.cjs';
|
|
6
6
|
export { g as generators } from './generators-BGtRGpJZ.cjs';
|
|
7
7
|
export { t as time } from './time-DbT8fjaF.cjs';
|
|
8
8
|
export { u as units } from './units-6lwDYBvX.cjs';
|
|
@@ -13,7 +13,7 @@ export { c as color } from './color-tPwZCr9H.cjs';
|
|
|
13
13
|
export { c as css } from './css-Cf7AMGM-.cjs';
|
|
14
14
|
export { m as misc } from './misc-CA3N198T.cjs';
|
|
15
15
|
export { a as ai_agent } from './ai_agent-CcpkV2DR.cjs';
|
|
16
|
-
export { m as media } from './media-
|
|
16
|
+
export { m as media } from './media-C3ZvGyKc.cjs';
|
|
17
17
|
|
|
18
18
|
declare const version = "0.1.0";
|
|
19
19
|
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { j as json } from './json-BjSoIS1h.js';
|
|
|
2
2
|
export { e as encoding } from './encoding-7gmq-vkV.js';
|
|
3
3
|
export { h as hashing } from './hashing-CnetQFD_.js';
|
|
4
4
|
export { t as text } from './text-Bbx-tZ43.js';
|
|
5
|
-
export { d as data } from './data-
|
|
5
|
+
export { d as data } from './data-D8XTI7Du.js';
|
|
6
6
|
export { g as generators } from './generators-BGtRGpJZ.js';
|
|
7
7
|
export { t as time } from './time-DbT8fjaF.js';
|
|
8
8
|
export { u as units } from './units-6lwDYBvX.js';
|
|
@@ -13,7 +13,7 @@ export { c as color } from './color-tPwZCr9H.js';
|
|
|
13
13
|
export { c as css } from './css-Cf7AMGM-.js';
|
|
14
14
|
export { m as misc } from './misc-CA3N198T.js';
|
|
15
15
|
export { a as ai_agent } from './ai_agent-CcpkV2DR.js';
|
|
16
|
-
export { m as media } from './media-
|
|
16
|
+
export { m as media } from './media-C3ZvGyKc.js';
|
|
17
17
|
|
|
18
18
|
declare const version = "0.1.0";
|
|
19
19
|
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { media_exports as media } from './chunk-
|
|
1
|
+
export { media_exports as media } from './chunk-GUUYEIU6.js';
|
|
2
2
|
export { units_exports as units } from './chunk-QJE743LY.js';
|
|
3
3
|
export { network_exports as network } from './chunk-V5JKVDBA.js';
|
|
4
4
|
export { api_exports as api } from './chunk-Q3B3YWOA.js';
|
|
@@ -11,7 +11,7 @@ export { json_exports as json } from './chunk-TSAGO3XP.js';
|
|
|
11
11
|
export { encoding_exports as encoding } from './chunk-IPR7FSX4.js';
|
|
12
12
|
export { hashing_exports as hashing } from './chunk-GEFVMGZR.js';
|
|
13
13
|
export { text_exports as text } from './chunk-F57WMKZO.js';
|
|
14
|
-
export { data_exports as data } from './chunk-
|
|
14
|
+
export { data_exports as data } from './chunk-TINQFTLO.js';
|
|
15
15
|
export { generators_exports as generators } from './chunk-2CJSLYWI.js';
|
|
16
16
|
export { time_exports as time } from './chunk-ZPQZEIXP.js';
|
|
17
17
|
import './chunk-MLKGABMK.js';
|
|
@@ -86,9 +86,33 @@ interface WavInfoError {
|
|
|
86
86
|
* rarer RF64 variant used for files over 4GB).
|
|
87
87
|
*/
|
|
88
88
|
declare function readWavInfo(bytes: Uint8Array): WavInfo | WavInfoError;
|
|
89
|
+
interface Id3Tags {
|
|
90
|
+
version: string;
|
|
91
|
+
title?: string;
|
|
92
|
+
artist?: string;
|
|
93
|
+
album?: string;
|
|
94
|
+
year?: string;
|
|
95
|
+
genre?: string;
|
|
96
|
+
comment?: string;
|
|
97
|
+
trackNumber?: string;
|
|
98
|
+
frameCount?: number;
|
|
99
|
+
}
|
|
100
|
+
interface Id3TagsError {
|
|
101
|
+
error: string;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Read ID3 tags (title, artist, album, year, genre, comment, track number)
|
|
105
|
+
* directly from an MP3 file's bytes, without any audio-decoding library.
|
|
106
|
+
* Prefers an ID3v2.3/2.4 header at the start of the file; falls back to a
|
|
107
|
+
* classic ID3v1/1.1 128-byte trailer if no ID3v2 text frames are found.
|
|
108
|
+
* ID3v2.2 tags are detected but their 3-character frame IDs are not decoded.
|
|
109
|
+
*/
|
|
110
|
+
declare function readId3Tags(bytes: Uint8Array): Id3Tags | Id3TagsError;
|
|
89
111
|
|
|
90
112
|
type media_ExifData = ExifData;
|
|
91
113
|
type media_ExifError = ExifError;
|
|
114
|
+
type media_Id3Tags = Id3Tags;
|
|
115
|
+
type media_Id3TagsError = Id3TagsError;
|
|
92
116
|
type media_ImageFormat = ImageFormat;
|
|
93
117
|
type media_ImageInfo = ImageInfo;
|
|
94
118
|
type media_ImageInfoError = ImageInfoError;
|
|
@@ -97,11 +121,12 @@ type media_PdfMetadataError = PdfMetadataError;
|
|
|
97
121
|
type media_WavInfo = WavInfo;
|
|
98
122
|
type media_WavInfoError = WavInfoError;
|
|
99
123
|
declare const media_readExifData: typeof readExifData;
|
|
124
|
+
declare const media_readId3Tags: typeof readId3Tags;
|
|
100
125
|
declare const media_readImageInfo: typeof readImageInfo;
|
|
101
126
|
declare const media_readPdfMetadata: typeof readPdfMetadata;
|
|
102
127
|
declare const media_readWavInfo: typeof readWavInfo;
|
|
103
128
|
declare namespace media {
|
|
104
|
-
export { type media_ExifData as ExifData, type media_ExifError as ExifError, type media_ImageFormat as ImageFormat, type media_ImageInfo as ImageInfo, type media_ImageInfoError as ImageInfoError, type media_PdfMetadata as PdfMetadata, type media_PdfMetadataError as PdfMetadataError, type media_WavInfo as WavInfo, type media_WavInfoError as WavInfoError, media_readExifData as readExifData, media_readImageInfo as readImageInfo, media_readPdfMetadata as readPdfMetadata, media_readWavInfo as readWavInfo };
|
|
129
|
+
export { type media_ExifData as ExifData, type media_ExifError as ExifError, type media_Id3Tags as Id3Tags, type media_Id3TagsError as Id3TagsError, type media_ImageFormat as ImageFormat, type media_ImageInfo as ImageInfo, type media_ImageInfoError as ImageInfoError, type media_PdfMetadata as PdfMetadata, type media_PdfMetadataError as PdfMetadataError, type media_WavInfo as WavInfo, type media_WavInfoError as WavInfoError, media_readExifData as readExifData, media_readId3Tags as readId3Tags, media_readImageInfo as readImageInfo, media_readPdfMetadata as readPdfMetadata, media_readWavInfo as readWavInfo };
|
|
105
130
|
}
|
|
106
131
|
|
|
107
|
-
export { type ExifData as E, type
|
|
132
|
+
export { type ExifData as E, type Id3Tags as I, type PdfMetadata as P, type WavInfo as W, type ExifError as a, type Id3TagsError as b, type ImageFormat as c, type ImageInfo as d, type ImageInfoError as e, type PdfMetadataError as f, type WavInfoError as g, readId3Tags as h, readImageInfo as i, readPdfMetadata as j, readWavInfo as k, media as m, readExifData as r };
|
|
@@ -86,9 +86,33 @@ interface WavInfoError {
|
|
|
86
86
|
* rarer RF64 variant used for files over 4GB).
|
|
87
87
|
*/
|
|
88
88
|
declare function readWavInfo(bytes: Uint8Array): WavInfo | WavInfoError;
|
|
89
|
+
interface Id3Tags {
|
|
90
|
+
version: string;
|
|
91
|
+
title?: string;
|
|
92
|
+
artist?: string;
|
|
93
|
+
album?: string;
|
|
94
|
+
year?: string;
|
|
95
|
+
genre?: string;
|
|
96
|
+
comment?: string;
|
|
97
|
+
trackNumber?: string;
|
|
98
|
+
frameCount?: number;
|
|
99
|
+
}
|
|
100
|
+
interface Id3TagsError {
|
|
101
|
+
error: string;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Read ID3 tags (title, artist, album, year, genre, comment, track number)
|
|
105
|
+
* directly from an MP3 file's bytes, without any audio-decoding library.
|
|
106
|
+
* Prefers an ID3v2.3/2.4 header at the start of the file; falls back to a
|
|
107
|
+
* classic ID3v1/1.1 128-byte trailer if no ID3v2 text frames are found.
|
|
108
|
+
* ID3v2.2 tags are detected but their 3-character frame IDs are not decoded.
|
|
109
|
+
*/
|
|
110
|
+
declare function readId3Tags(bytes: Uint8Array): Id3Tags | Id3TagsError;
|
|
89
111
|
|
|
90
112
|
type media_ExifData = ExifData;
|
|
91
113
|
type media_ExifError = ExifError;
|
|
114
|
+
type media_Id3Tags = Id3Tags;
|
|
115
|
+
type media_Id3TagsError = Id3TagsError;
|
|
92
116
|
type media_ImageFormat = ImageFormat;
|
|
93
117
|
type media_ImageInfo = ImageInfo;
|
|
94
118
|
type media_ImageInfoError = ImageInfoError;
|
|
@@ -97,11 +121,12 @@ type media_PdfMetadataError = PdfMetadataError;
|
|
|
97
121
|
type media_WavInfo = WavInfo;
|
|
98
122
|
type media_WavInfoError = WavInfoError;
|
|
99
123
|
declare const media_readExifData: typeof readExifData;
|
|
124
|
+
declare const media_readId3Tags: typeof readId3Tags;
|
|
100
125
|
declare const media_readImageInfo: typeof readImageInfo;
|
|
101
126
|
declare const media_readPdfMetadata: typeof readPdfMetadata;
|
|
102
127
|
declare const media_readWavInfo: typeof readWavInfo;
|
|
103
128
|
declare namespace media {
|
|
104
|
-
export { type media_ExifData as ExifData, type media_ExifError as ExifError, type media_ImageFormat as ImageFormat, type media_ImageInfo as ImageInfo, type media_ImageInfoError as ImageInfoError, type media_PdfMetadata as PdfMetadata, type media_PdfMetadataError as PdfMetadataError, type media_WavInfo as WavInfo, type media_WavInfoError as WavInfoError, media_readExifData as readExifData, media_readImageInfo as readImageInfo, media_readPdfMetadata as readPdfMetadata, media_readWavInfo as readWavInfo };
|
|
129
|
+
export { type media_ExifData as ExifData, type media_ExifError as ExifError, type media_Id3Tags as Id3Tags, type media_Id3TagsError as Id3TagsError, type media_ImageFormat as ImageFormat, type media_ImageInfo as ImageInfo, type media_ImageInfoError as ImageInfoError, type media_PdfMetadata as PdfMetadata, type media_PdfMetadataError as PdfMetadataError, type media_WavInfo as WavInfo, type media_WavInfoError as WavInfoError, media_readExifData as readExifData, media_readId3Tags as readId3Tags, media_readImageInfo as readImageInfo, media_readPdfMetadata as readPdfMetadata, media_readWavInfo as readWavInfo };
|
|
105
130
|
}
|
|
106
131
|
|
|
107
|
-
export { type ExifData as E, type
|
|
132
|
+
export { type ExifData as E, type Id3Tags as I, type PdfMetadata as P, type WavInfo as W, type ExifError as a, type Id3TagsError as b, type ImageFormat as c, type ImageInfo as d, type ImageInfoError as e, type PdfMetadataError as f, type WavInfoError as g, readId3Tags as h, readImageInfo as i, readPdfMetadata as j, readWavInfo as k, media as m, readExifData as r };
|
package/dist/tools/data.cjs
CHANGED
|
@@ -1064,6 +1064,23 @@ function envToExport(input) {
|
|
|
1064
1064
|
function validateEnvKey(key) {
|
|
1065
1065
|
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key);
|
|
1066
1066
|
}
|
|
1067
|
+
function diffEnvExample(envInput, exampleInput) {
|
|
1068
|
+
const envParsed = parseEnv(envInput);
|
|
1069
|
+
if (envParsed.errors.length > 0) {
|
|
1070
|
+
return { error: `.env: ${envParsed.errors.map((e) => `Line ${e.line}: ${e.message}`).join("; ")}` };
|
|
1071
|
+
}
|
|
1072
|
+
const exampleParsed = parseEnv(exampleInput);
|
|
1073
|
+
if (exampleParsed.errors.length > 0) {
|
|
1074
|
+
return { error: `.env.example: ${exampleParsed.errors.map((e) => `Line ${e.line}: ${e.message}`).join("; ")}` };
|
|
1075
|
+
}
|
|
1076
|
+
const envKeys = new Set(envParsed.entries.map((e) => e.key));
|
|
1077
|
+
const exampleValues = new Map(exampleParsed.entries.map((e) => [e.key, e.value]));
|
|
1078
|
+
const missingInExample = [...envKeys].filter((k) => !exampleValues.has(k)).sort();
|
|
1079
|
+
const missingInEnv = [...exampleValues.keys()].filter((k) => !envKeys.has(k)).sort();
|
|
1080
|
+
const emptyValueInExample = [...exampleValues.entries()].filter(([k, v]) => envKeys.has(k) && v === "").map(([k]) => k).sort();
|
|
1081
|
+
const keysInBoth = [...envKeys].filter((k) => exampleValues.has(k)).length;
|
|
1082
|
+
return { missingInExample, missingInEnv, emptyValueInExample, keysInBoth };
|
|
1083
|
+
}
|
|
1067
1084
|
function validateNdjson(input) {
|
|
1068
1085
|
const rawLines = input.split("\n");
|
|
1069
1086
|
const lines = [];
|
|
@@ -1125,6 +1142,7 @@ function jsonArrayToNdjson(input) {
|
|
|
1125
1142
|
|
|
1126
1143
|
exports.csvToJson = csvToJson;
|
|
1127
1144
|
exports.detectDelimiter = detectDelimiter;
|
|
1145
|
+
exports.diffEnvExample = diffEnvExample;
|
|
1128
1146
|
exports.envToExport = envToExport;
|
|
1129
1147
|
exports.envToJson = envToJson;
|
|
1130
1148
|
exports.formatNdjson = formatNdjson;
|
package/dist/tools/data.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { C as CsvParseResult, E as
|
|
1
|
+
export { C as CsvParseResult, E as EnvDiffError, a as EnvDiffResult, b as EnvEntry, c as EnvParseResult, I as IniSection, N as NdjsonLineResult, e as NdjsonValidateResult, P as ParseOptions, f as ParsedIni, T as TomlFormatResult, V as ValidationResult, X as XmlFormatResult, g as XmlToJsonOptions, h as csvToJson, i as detectDelimiter, j as diffEnvExample, k as envToExport, l as envToJson, m as formatNdjson, n as formatToml, o as formatXml, p as getSection, q as getSectionNames, r as getTomlStats, s as getXmlStats, t as getYamlStats, u as iniToJson, v as jsonArrayToNdjson, w as jsonToIni, x as jsonToToml, y as jsonToXml, z as minifyNdjson, A as minifyToml, B as minifyXml, D as ndjsonToJsonArray, F as parseCsv, G as parseEnv, H as parseIni, J as parseXmlToObject, K as stringifyIni, L as toCsvString, M as tomlToJson, O as validateEnvKey, Q as validateIni, R as validateNdjson, S as validateToml, U as validateXml, W as validateYaml, Y as xmlToJson } from '../data-D8XTI7Du.cjs';
|
package/dist/tools/data.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { C as CsvParseResult, E as
|
|
1
|
+
export { C as CsvParseResult, E as EnvDiffError, a as EnvDiffResult, b as EnvEntry, c as EnvParseResult, I as IniSection, N as NdjsonLineResult, e as NdjsonValidateResult, P as ParseOptions, f as ParsedIni, T as TomlFormatResult, V as ValidationResult, X as XmlFormatResult, g as XmlToJsonOptions, h as csvToJson, i as detectDelimiter, j as diffEnvExample, k as envToExport, l as envToJson, m as formatNdjson, n as formatToml, o as formatXml, p as getSection, q as getSectionNames, r as getTomlStats, s as getXmlStats, t as getYamlStats, u as iniToJson, v as jsonArrayToNdjson, w as jsonToIni, x as jsonToToml, y as jsonToXml, z as minifyNdjson, A as minifyToml, B as minifyXml, D as ndjsonToJsonArray, F as parseCsv, G as parseEnv, H as parseIni, J as parseXmlToObject, K as stringifyIni, L as toCsvString, M as tomlToJson, O as validateEnvKey, Q as validateIni, R as validateNdjson, S as validateToml, U as validateXml, W as validateYaml, Y as xmlToJson } from '../data-D8XTI7Du.js';
|
package/dist/tools/data.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { csvToJson, detectDelimiter, envToExport, envToJson, formatNdjson, formatToml, formatXml, getSection, getSectionNames, getTomlStats, getXmlStats, getYamlStats, iniToJson, jsonArrayToNdjson, jsonToIni, jsonToToml, jsonToXml, minifyNdjson, minifyToml, minifyXml, ndjsonToJsonArray, parseCsv, parseEnv, parseIni, parseXmlToObject, stringifyIni, toCsvString, tomlToJson, validateEnvKey, validateIni, validateNdjson, validateToml, validateXml, validateYaml, xmlToJson } from '../chunk-
|
|
1
|
+
export { csvToJson, detectDelimiter, diffEnvExample, envToExport, envToJson, formatNdjson, formatToml, formatXml, getSection, getSectionNames, getTomlStats, getXmlStats, getYamlStats, iniToJson, jsonArrayToNdjson, jsonToIni, jsonToToml, jsonToXml, minifyNdjson, minifyToml, minifyXml, ndjsonToJsonArray, parseCsv, parseEnv, parseIni, parseXmlToObject, stringifyIni, toCsvString, tomlToJson, validateEnvKey, validateIni, validateNdjson, validateToml, validateXml, validateYaml, xmlToJson } from '../chunk-TINQFTLO.js';
|
|
2
2
|
import '../chunk-MLKGABMK.js';
|
package/dist/tools/media.cjs
CHANGED
|
@@ -513,8 +513,218 @@ function readWavInfo(bytes) {
|
|
|
513
513
|
fileSize
|
|
514
514
|
};
|
|
515
515
|
}
|
|
516
|
+
var ID3V1_GENRES = [
|
|
517
|
+
"Blues",
|
|
518
|
+
"Classic Rock",
|
|
519
|
+
"Country",
|
|
520
|
+
"Dance",
|
|
521
|
+
"Disco",
|
|
522
|
+
"Funk",
|
|
523
|
+
"Grunge",
|
|
524
|
+
"Hip-Hop",
|
|
525
|
+
"Jazz",
|
|
526
|
+
"Metal",
|
|
527
|
+
"New Age",
|
|
528
|
+
"Oldies",
|
|
529
|
+
"Other",
|
|
530
|
+
"Pop",
|
|
531
|
+
"R&B",
|
|
532
|
+
"Rap",
|
|
533
|
+
"Reggae",
|
|
534
|
+
"Rock",
|
|
535
|
+
"Techno",
|
|
536
|
+
"Industrial",
|
|
537
|
+
"Alternative",
|
|
538
|
+
"Ska",
|
|
539
|
+
"Death Metal",
|
|
540
|
+
"Pranks",
|
|
541
|
+
"Soundtrack",
|
|
542
|
+
"Euro-Techno",
|
|
543
|
+
"Ambient",
|
|
544
|
+
"Trip-Hop",
|
|
545
|
+
"Vocal",
|
|
546
|
+
"Jazz+Funk",
|
|
547
|
+
"Fusion",
|
|
548
|
+
"Trance",
|
|
549
|
+
"Classical",
|
|
550
|
+
"Instrumental",
|
|
551
|
+
"Acid",
|
|
552
|
+
"House",
|
|
553
|
+
"Game",
|
|
554
|
+
"Sound Clip",
|
|
555
|
+
"Gospel",
|
|
556
|
+
"Noise",
|
|
557
|
+
"AlternRock",
|
|
558
|
+
"Bass",
|
|
559
|
+
"Soul",
|
|
560
|
+
"Punk",
|
|
561
|
+
"Space",
|
|
562
|
+
"Meditative",
|
|
563
|
+
"Instrumental Pop",
|
|
564
|
+
"Instrumental Rock",
|
|
565
|
+
"Ethnic",
|
|
566
|
+
"Gothic",
|
|
567
|
+
"Darkwave",
|
|
568
|
+
"Techno-Industrial",
|
|
569
|
+
"Electronic",
|
|
570
|
+
"Pop-Folk",
|
|
571
|
+
"Eurodance",
|
|
572
|
+
"Dream",
|
|
573
|
+
"Southern Rock",
|
|
574
|
+
"Comedy",
|
|
575
|
+
"Cult",
|
|
576
|
+
"Gangsta",
|
|
577
|
+
"Top 40",
|
|
578
|
+
"Christian Rap",
|
|
579
|
+
"Pop/Funk",
|
|
580
|
+
"Jungle",
|
|
581
|
+
"Native American",
|
|
582
|
+
"Cabaret",
|
|
583
|
+
"New Wave",
|
|
584
|
+
"Psychedelic",
|
|
585
|
+
"Rave",
|
|
586
|
+
"Showtunes",
|
|
587
|
+
"Trailer",
|
|
588
|
+
"Lo-Fi",
|
|
589
|
+
"Tribal",
|
|
590
|
+
"Acid Punk",
|
|
591
|
+
"Acid Jazz",
|
|
592
|
+
"Polka",
|
|
593
|
+
"Retro",
|
|
594
|
+
"Musical",
|
|
595
|
+
"Rock & Roll",
|
|
596
|
+
"Hard Rock"
|
|
597
|
+
];
|
|
598
|
+
function readSynchsafeUInt32(bytes, offset) {
|
|
599
|
+
return (bytes[offset] & 127) << 21 | (bytes[offset + 1] & 127) << 14 | (bytes[offset + 2] & 127) << 7 | bytes[offset + 3] & 127;
|
|
600
|
+
}
|
|
601
|
+
function readUInt32BE(bytes, offset) {
|
|
602
|
+
return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
|
|
603
|
+
}
|
|
604
|
+
function decodeId3Text(frameBytes) {
|
|
605
|
+
if (frameBytes.length === 0) return "";
|
|
606
|
+
const encodingByte = frameBytes[0];
|
|
607
|
+
const content = frameBytes.subarray(1);
|
|
608
|
+
let out = "";
|
|
609
|
+
if (encodingByte === 3) {
|
|
610
|
+
out = Buffer.from(content).toString("utf8");
|
|
611
|
+
} else if (encodingByte === 1 || encodingByte === 2) {
|
|
612
|
+
let little = encodingByte === 1;
|
|
613
|
+
let start = 0;
|
|
614
|
+
if (encodingByte === 1 && content.length >= 2) {
|
|
615
|
+
if (content[0] === 255 && content[1] === 254) {
|
|
616
|
+
little = true;
|
|
617
|
+
start = 2;
|
|
618
|
+
} else if (content[0] === 254 && content[1] === 255) {
|
|
619
|
+
little = false;
|
|
620
|
+
start = 2;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
for (let i = start; i + 1 < content.length; i += 2) {
|
|
624
|
+
const code = little ? content[i] | content[i + 1] << 8 : content[i] << 8 | content[i + 1];
|
|
625
|
+
if (code === 0) break;
|
|
626
|
+
out += String.fromCharCode(code);
|
|
627
|
+
}
|
|
628
|
+
} else {
|
|
629
|
+
for (const b of content) {
|
|
630
|
+
if (b === 0) break;
|
|
631
|
+
out += String.fromCharCode(b);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return out.replace(/\0+$/, "").trim();
|
|
635
|
+
}
|
|
636
|
+
function readId3v2(bytes) {
|
|
637
|
+
if (bytes.length < 10 || bytes[0] !== 73 || bytes[1] !== 68 || bytes[2] !== 51) return null;
|
|
638
|
+
const majorVersion = bytes[3];
|
|
639
|
+
const revision = bytes[4];
|
|
640
|
+
const tagSize = readSynchsafeUInt32(bytes, 6);
|
|
641
|
+
const version = `ID3v2.${majorVersion}.${revision}`;
|
|
642
|
+
if (majorVersion !== 3 && majorVersion !== 4) {
|
|
643
|
+
return { version, frames: {}, frameCount: 0 };
|
|
644
|
+
}
|
|
645
|
+
const frames = {};
|
|
646
|
+
let offset = 10;
|
|
647
|
+
const end = Math.min(10 + tagSize, bytes.length);
|
|
648
|
+
let frameCount = 0;
|
|
649
|
+
while (offset + 10 <= end) {
|
|
650
|
+
const frameId = String.fromCharCode(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]);
|
|
651
|
+
if (frameId === "\0\0\0\0") break;
|
|
652
|
+
const frameSize = majorVersion === 4 ? readSynchsafeUInt32(bytes, offset + 4) : readUInt32BE(bytes, offset + 4);
|
|
653
|
+
const frameStart = offset + 10;
|
|
654
|
+
if (frameSize <= 0 || frameStart + frameSize > bytes.length) break;
|
|
655
|
+
const frameBytes = bytes.subarray(frameStart, frameStart + frameSize);
|
|
656
|
+
if (frameId[0] === "T" && frameId !== "TXXX") {
|
|
657
|
+
frames[frameId] = decodeId3Text(frameBytes);
|
|
658
|
+
} else if (frameId === "COMM" && frameBytes.length > 4) {
|
|
659
|
+
const rebuilt = new Uint8Array(frameBytes.length - 3);
|
|
660
|
+
rebuilt[0] = frameBytes[0];
|
|
661
|
+
rebuilt.set(frameBytes.subarray(4), 1);
|
|
662
|
+
const decoded = decodeId3Text(rebuilt);
|
|
663
|
+
const parts = decoded.split("\0");
|
|
664
|
+
frames["COMM"] = (parts[parts.length - 1] || decoded).trim();
|
|
665
|
+
}
|
|
666
|
+
frameCount++;
|
|
667
|
+
offset = frameStart + frameSize;
|
|
668
|
+
}
|
|
669
|
+
return { version, frames, frameCount };
|
|
670
|
+
}
|
|
671
|
+
function readId3v1(bytes) {
|
|
672
|
+
if (bytes.length < 128) return null;
|
|
673
|
+
const start = bytes.length - 128;
|
|
674
|
+
if (String.fromCharCode(bytes[start], bytes[start + 1], bytes[start + 2]) !== "TAG") return null;
|
|
675
|
+
const readField = (offset, length) => {
|
|
676
|
+
let s = "";
|
|
677
|
+
for (let i = 0; i < length; i++) {
|
|
678
|
+
const b = bytes[start + offset + i];
|
|
679
|
+
if (b === 0) break;
|
|
680
|
+
s += String.fromCharCode(b);
|
|
681
|
+
}
|
|
682
|
+
return s.trim();
|
|
683
|
+
};
|
|
684
|
+
const title = readField(3, 30);
|
|
685
|
+
const artist = readField(33, 30);
|
|
686
|
+
const album = readField(63, 30);
|
|
687
|
+
const year = readField(93, 4);
|
|
688
|
+
const isV11 = bytes[start + 125] === 0 && bytes[start + 126] !== 0;
|
|
689
|
+
const comment = readField(97, isV11 ? 28 : 30);
|
|
690
|
+
const genreIndex = bytes[start + 127];
|
|
691
|
+
const genre = ID3V1_GENRES[genreIndex] ?? `Unknown (${genreIndex})`;
|
|
692
|
+
const result = { genre };
|
|
693
|
+
if (title) result.title = title;
|
|
694
|
+
if (artist) result.artist = artist;
|
|
695
|
+
if (album) result.album = album;
|
|
696
|
+
if (year) result.year = year;
|
|
697
|
+
if (comment) result.comment = comment;
|
|
698
|
+
if (isV11) result.trackNumber = String(bytes[start + 126]);
|
|
699
|
+
return result;
|
|
700
|
+
}
|
|
701
|
+
function readId3Tags(bytes) {
|
|
702
|
+
const v2 = readId3v2(bytes);
|
|
703
|
+
const v1 = readId3v1(bytes);
|
|
704
|
+
if (v2 && Object.keys(v2.frames).length > 0) {
|
|
705
|
+
const f = v2.frames;
|
|
706
|
+
const result = { version: v2.version, frameCount: v2.frameCount };
|
|
707
|
+
if (f["TIT2"]) result.title = f["TIT2"];
|
|
708
|
+
if (f["TPE1"]) result.artist = f["TPE1"];
|
|
709
|
+
if (f["TALB"]) result.album = f["TALB"];
|
|
710
|
+
const year = f["TYER"] || f["TDRC"];
|
|
711
|
+
if (year) result.year = year;
|
|
712
|
+
if (f["TCON"]) result.genre = f["TCON"];
|
|
713
|
+
if (f["COMM"]) result.comment = f["COMM"];
|
|
714
|
+
if (f["TRCK"]) result.trackNumber = f["TRCK"];
|
|
715
|
+
return result;
|
|
716
|
+
}
|
|
717
|
+
if (v1) {
|
|
718
|
+
return { version: v1.trackNumber !== void 0 ? "ID3v1.1" : "ID3v1", ...v1 };
|
|
719
|
+
}
|
|
720
|
+
if (v2) {
|
|
721
|
+
return { error: `Unsupported ID3 tag version: ${v2.version} (only ID3v2.3, ID3v2.4, and ID3v1/1.1 are supported)` };
|
|
722
|
+
}
|
|
723
|
+
return { error: "No ID3v1 or ID3v2.3/2.4 tags found in this file" };
|
|
724
|
+
}
|
|
516
725
|
|
|
517
726
|
exports.readExifData = readExifData;
|
|
727
|
+
exports.readId3Tags = readId3Tags;
|
|
518
728
|
exports.readImageInfo = readImageInfo;
|
|
519
729
|
exports.readPdfMetadata = readPdfMetadata;
|
|
520
730
|
exports.readWavInfo = readWavInfo;
|
package/dist/tools/media.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { E as ExifData, a as ExifError, I as
|
|
1
|
+
export { E as ExifData, a as ExifError, I as Id3Tags, b as Id3TagsError, c as ImageFormat, d as ImageInfo, e as ImageInfoError, P as PdfMetadata, f as PdfMetadataError, W as WavInfo, g as WavInfoError, r as readExifData, h as readId3Tags, i as readImageInfo, j as readPdfMetadata, k as readWavInfo } from '../media-C3ZvGyKc.cjs';
|
package/dist/tools/media.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { E as ExifData, a as ExifError, I as
|
|
1
|
+
export { E as ExifData, a as ExifError, I as Id3Tags, b as Id3TagsError, c as ImageFormat, d as ImageInfo, e as ImageInfoError, P as PdfMetadata, f as PdfMetadataError, W as WavInfo, g as WavInfoError, r as readExifData, h as readId3Tags, i as readImageInfo, j as readPdfMetadata, k as readWavInfo } from '../media-C3ZvGyKc.js';
|
package/dist/tools/media.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { readExifData, readImageInfo, readPdfMetadata, readWavInfo } from '../chunk-
|
|
1
|
+
export { readExifData, readId3Tags, readImageInfo, readPdfMetadata, readWavInfo } from '../chunk-GUUYEIU6.js';
|
|
2
2
|
import '../chunk-MLKGABMK.js';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@utilix-tech/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "153+ developer utility tools for Node.js: JSON, encoding, hashing, color, CSS, network and more. Runs locally, no API key required.",
|
|
5
5
|
"author": "Utilix <hello@utilix.tech>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://www.utilix.tech/docs#node-sdk",
|
|
@@ -28,7 +28,12 @@
|
|
|
28
28
|
"regex",
|
|
29
29
|
"uuid",
|
|
30
30
|
"api-client",
|
|
31
|
-
"utilix"
|
|
31
|
+
"utilix",
|
|
32
|
+
"ai-agent",
|
|
33
|
+
"llm-tools",
|
|
34
|
+
"rag",
|
|
35
|
+
"yaml",
|
|
36
|
+
"base64"
|
|
32
37
|
],
|
|
33
38
|
"engines": {
|
|
34
39
|
"node": ">=18"
|