@utilix-tech/sdk 0.4.0 → 0.5.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/README.md +16 -6
- package/dist/{api-8aZtWhSj.d.cts → api-Xl7OzIgq.d.cts} +35 -2
- package/dist/{api-8aZtWhSj.d.ts → api-Xl7OzIgq.d.ts} +35 -2
- package/dist/{chunk-HFRTZE7T.js → chunk-Q3B3YWOA.js} +51 -1
- package/dist/chunk-WWKPLYEP.js +277 -0
- package/dist/index.cjs +194 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/media-D-K5aZnq.d.cts +53 -0
- package/dist/media-D-K5aZnq.d.ts +53 -0
- package/dist/tools/api.cjs +50 -0
- package/dist/tools/api.d.cts +1 -1
- package/dist/tools/api.d.ts +1 -1
- package/dist/tools/api.js +1 -1
- package/dist/tools/media.cjs +143 -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 +1 -1
- package/dist/chunk-N7C52YGL.js +0 -134
- package/dist/media-DF2cx3pK.d.cts +0 -28
- package/dist/media-DF2cx3pK.d.ts +0 -28
package/dist/index.cjs
CHANGED
|
@@ -8894,6 +8894,7 @@ __export(api_exports, {
|
|
|
8894
8894
|
parseCspHeader: () => parseCspHeader,
|
|
8895
8895
|
parseCurl: () => parseCurl,
|
|
8896
8896
|
parseCurlCommand: () => parseCurlCommand,
|
|
8897
|
+
parseJwks: () => parseJwks,
|
|
8897
8898
|
parseMetaTags: () => parseMetaTags,
|
|
8898
8899
|
parseUrl: () => parseUrl,
|
|
8899
8900
|
removeParam: () => removeParam,
|
|
@@ -9343,6 +9344,55 @@ function decodeJwt(token) {
|
|
|
9343
9344
|
function formatJwtJson(obj) {
|
|
9344
9345
|
return JSON.stringify(obj, null, 2);
|
|
9345
9346
|
}
|
|
9347
|
+
function base64urlByteLength(s) {
|
|
9348
|
+
const clean = s.replace(/=+$/, "");
|
|
9349
|
+
return Math.floor(clean.length * 6 / 8);
|
|
9350
|
+
}
|
|
9351
|
+
function parseJwks(input) {
|
|
9352
|
+
const trimmed = input.trim();
|
|
9353
|
+
if (!trimmed) return { ok: false, error: "No input provided" };
|
|
9354
|
+
let data;
|
|
9355
|
+
try {
|
|
9356
|
+
data = JSON.parse(trimmed);
|
|
9357
|
+
} catch (e) {
|
|
9358
|
+
return { ok: false, error: `Invalid JSON: ${e instanceof Error ? e.message : String(e)}` };
|
|
9359
|
+
}
|
|
9360
|
+
let rawKeys;
|
|
9361
|
+
if (data && typeof data === "object" && Array.isArray(data.keys)) {
|
|
9362
|
+
rawKeys = data.keys;
|
|
9363
|
+
} else if (data && typeof data === "object" && typeof data.kty === "string") {
|
|
9364
|
+
rawKeys = [data];
|
|
9365
|
+
} else {
|
|
9366
|
+
return { ok: false, error: 'Input must be a JWKS object with a "keys" array, or a single JWK object with a "kty" field' };
|
|
9367
|
+
}
|
|
9368
|
+
const keys = rawKeys.map((k) => {
|
|
9369
|
+
const key = k ?? {};
|
|
9370
|
+
const kty = typeof key.kty === "string" ? key.kty : "unknown";
|
|
9371
|
+
let keySize = null;
|
|
9372
|
+
let curve;
|
|
9373
|
+
if (kty === "RSA" && typeof key.n === "string") {
|
|
9374
|
+
keySize = base64urlByteLength(key.n) * 8;
|
|
9375
|
+
} else if ((kty === "EC" || kty === "OKP") && typeof key.crv === "string") {
|
|
9376
|
+
curve = key.crv;
|
|
9377
|
+
} else if (kty === "oct" && typeof key.k === "string") {
|
|
9378
|
+
keySize = base64urlByteLength(key.k) * 8;
|
|
9379
|
+
}
|
|
9380
|
+
return {
|
|
9381
|
+
kty,
|
|
9382
|
+
use: typeof key.use === "string" ? key.use : void 0,
|
|
9383
|
+
keyOps: Array.isArray(key.key_ops) ? key.key_ops.filter((x) => typeof x === "string") : void 0,
|
|
9384
|
+
alg: typeof key.alg === "string" ? key.alg : void 0,
|
|
9385
|
+
kid: typeof key.kid === "string" ? key.kid : void 0,
|
|
9386
|
+
keySize,
|
|
9387
|
+
curve,
|
|
9388
|
+
raw: key
|
|
9389
|
+
};
|
|
9390
|
+
});
|
|
9391
|
+
const kidCounts = /* @__PURE__ */ new Map();
|
|
9392
|
+
for (const k of keys) if (k.kid) kidCounts.set(k.kid, (kidCounts.get(k.kid) ?? 0) + 1);
|
|
9393
|
+
const duplicateKids = [...kidCounts.entries()].filter(([, c]) => c > 1).map(([kid]) => kid);
|
|
9394
|
+
return { ok: true, keys, count: keys.length, duplicateKids };
|
|
9395
|
+
}
|
|
9346
9396
|
var ALG_TO_NODE_HASH = {
|
|
9347
9397
|
HS256: "sha256",
|
|
9348
9398
|
HS384: "sha384",
|
|
@@ -16884,7 +16934,8 @@ function summarizeForLlm(text, maxTokens = 200, strategy = "extractive") {
|
|
|
16884
16934
|
// src/tools/media.ts
|
|
16885
16935
|
var media_exports = {};
|
|
16886
16936
|
__export(media_exports, {
|
|
16887
|
-
readImageInfo: () => readImageInfo
|
|
16937
|
+
readImageInfo: () => readImageInfo,
|
|
16938
|
+
readPdfMetadata: () => readPdfMetadata
|
|
16888
16939
|
});
|
|
16889
16940
|
function readU32BE(bytes, offset) {
|
|
16890
16941
|
return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
|
|
@@ -17011,6 +17062,148 @@ function readImageInfo(bytes) {
|
|
|
17011
17062
|
}
|
|
17012
17063
|
return { error: "Unrecognized image format. Supported formats: PNG, JPEG, GIF, WebP, BMP" };
|
|
17013
17064
|
}
|
|
17065
|
+
function bytesToLatin1(bytes) {
|
|
17066
|
+
let out = "";
|
|
17067
|
+
const CHUNK = 32768;
|
|
17068
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
17069
|
+
out += String.fromCharCode(...bytes.subarray(i, i + CHUNK));
|
|
17070
|
+
}
|
|
17071
|
+
return out;
|
|
17072
|
+
}
|
|
17073
|
+
function decodePdfString(raw, isHex) {
|
|
17074
|
+
const bytes = [];
|
|
17075
|
+
if (isHex) {
|
|
17076
|
+
const hex = raw.replace(/\s+/g, "");
|
|
17077
|
+
const padded = hex.length % 2 === 0 ? hex : hex + "0";
|
|
17078
|
+
for (let i = 0; i < padded.length; i += 2) bytes.push(parseInt(padded.slice(i, i + 2), 16));
|
|
17079
|
+
} else {
|
|
17080
|
+
const s = raw.replace(/\\\r\n|\\\r|\\\n/g, "");
|
|
17081
|
+
for (let i = 0; i < s.length; i++) {
|
|
17082
|
+
const ch = s[i];
|
|
17083
|
+
if (ch === "\\" && i + 1 < s.length) {
|
|
17084
|
+
const next = s[i + 1];
|
|
17085
|
+
if (next === "n") {
|
|
17086
|
+
bytes.push(10);
|
|
17087
|
+
i++;
|
|
17088
|
+
} else if (next === "r") {
|
|
17089
|
+
bytes.push(13);
|
|
17090
|
+
i++;
|
|
17091
|
+
} else if (next === "t") {
|
|
17092
|
+
bytes.push(9);
|
|
17093
|
+
i++;
|
|
17094
|
+
} else if (next === "b") {
|
|
17095
|
+
bytes.push(8);
|
|
17096
|
+
i++;
|
|
17097
|
+
} else if (next === "f") {
|
|
17098
|
+
bytes.push(12);
|
|
17099
|
+
i++;
|
|
17100
|
+
} else if (next === "(" || next === ")" || next === "\\") {
|
|
17101
|
+
bytes.push(next.charCodeAt(0));
|
|
17102
|
+
i++;
|
|
17103
|
+
} else if (/[0-7]/.test(next)) {
|
|
17104
|
+
let oct = next;
|
|
17105
|
+
i++;
|
|
17106
|
+
for (let k = 0; k < 2 && i + 1 < s.length && /[0-7]/.test(s[i + 1]); k++) {
|
|
17107
|
+
i++;
|
|
17108
|
+
oct += s[i];
|
|
17109
|
+
}
|
|
17110
|
+
bytes.push(parseInt(oct, 8) & 255);
|
|
17111
|
+
} else {
|
|
17112
|
+
bytes.push(next.charCodeAt(0));
|
|
17113
|
+
i++;
|
|
17114
|
+
}
|
|
17115
|
+
} else {
|
|
17116
|
+
bytes.push(ch.charCodeAt(0) & 255);
|
|
17117
|
+
}
|
|
17118
|
+
}
|
|
17119
|
+
}
|
|
17120
|
+
if (bytes.length >= 2 && bytes[0] === 254 && bytes[1] === 255) {
|
|
17121
|
+
let out = "";
|
|
17122
|
+
for (let i = 2; i + 1 < bytes.length; i += 2) out += String.fromCharCode(bytes[i] << 8 | bytes[i + 1]);
|
|
17123
|
+
return out;
|
|
17124
|
+
}
|
|
17125
|
+
return bytes.map((b) => String.fromCharCode(b)).join("");
|
|
17126
|
+
}
|
|
17127
|
+
function extractDictField(dict, key) {
|
|
17128
|
+
const litMatch = dict.match(new RegExp(`/${key}\\s*\\(((?:\\\\.|[^\\\\()])*)\\)`));
|
|
17129
|
+
if (litMatch) return decodePdfString(litMatch[1], false);
|
|
17130
|
+
const hexMatch = dict.match(new RegExp(`/${key}\\s*<([0-9A-Fa-f\\s]*)>`));
|
|
17131
|
+
if (hexMatch) return decodePdfString(hexMatch[1], true);
|
|
17132
|
+
return null;
|
|
17133
|
+
}
|
|
17134
|
+
function findObject(text, objNum, gen) {
|
|
17135
|
+
const m = text.match(new RegExp(`(?:^|[^0-9])${objNum}\\s+${gen}\\s+obj([\\s\\S]*?)endobj`));
|
|
17136
|
+
return m ? m[1] : null;
|
|
17137
|
+
}
|
|
17138
|
+
function parsePdfDate(raw) {
|
|
17139
|
+
const m = raw.match(/^D:(\d{4})(\d{2})?(\d{2})?(\d{2})?(\d{2})?(\d{2})?([Z+-])?(\d{2})?'?(\d{2})?'?/);
|
|
17140
|
+
if (!m) return null;
|
|
17141
|
+
const [, y, mo = "01", d = "01", h = "00", mi = "00", s = "00", tz, tzh, tzm] = m;
|
|
17142
|
+
let iso = `${y}-${mo}-${d}T${h}:${mi}:${s}`;
|
|
17143
|
+
if (tz === "Z") iso += "Z";
|
|
17144
|
+
else if (tz === "+" || tz === "-") iso += `${tz}${tzh ?? "00"}:${tzm ?? "00"}`;
|
|
17145
|
+
return iso;
|
|
17146
|
+
}
|
|
17147
|
+
function readPdfMetadata(bytes) {
|
|
17148
|
+
if (bytes.length < 8) return { error: "File too small to be a PDF" };
|
|
17149
|
+
const header = bytesToLatin1(bytes.subarray(0, 16));
|
|
17150
|
+
const versionMatch = header.match(/%PDF-(\d\.\d)/);
|
|
17151
|
+
if (!versionMatch) return { error: "Not a valid PDF file (missing %PDF header)" };
|
|
17152
|
+
const version2 = versionMatch[1];
|
|
17153
|
+
const text = bytesToLatin1(bytes);
|
|
17154
|
+
const trailerMatches = [...text.matchAll(/trailer\s*<<([\s\S]*?)>>/g)];
|
|
17155
|
+
let infoDict = null;
|
|
17156
|
+
let encrypted = false;
|
|
17157
|
+
if (trailerMatches.length > 0) {
|
|
17158
|
+
const trailer = trailerMatches[trailerMatches.length - 1][1];
|
|
17159
|
+
encrypted = /\/Encrypt\s+\d+\s+\d+\s+R/.test(trailer);
|
|
17160
|
+
const infoRef = trailer.match(/\/Info\s+(\d+)\s+(\d+)\s+R/);
|
|
17161
|
+
if (infoRef) infoDict = findObject(text, Number(infoRef[1]), Number(infoRef[2]));
|
|
17162
|
+
}
|
|
17163
|
+
const objBlocks = [...text.matchAll(/(\d+)\s+(\d+)\s+obj([\s\S]*?)endobj/g)];
|
|
17164
|
+
if (!infoDict) {
|
|
17165
|
+
for (const b of objBlocks) {
|
|
17166
|
+
if (/\/(Title|Author|Producer|Creator|CreationDate)\b/.test(b[3]) && !/\/Type\s*\/(Page|Pages|Catalog|Font)\b/.test(b[3])) {
|
|
17167
|
+
infoDict = b[3];
|
|
17168
|
+
break;
|
|
17169
|
+
}
|
|
17170
|
+
}
|
|
17171
|
+
}
|
|
17172
|
+
const title = infoDict ? extractDictField(infoDict, "Title") : null;
|
|
17173
|
+
const author = infoDict ? extractDictField(infoDict, "Author") : null;
|
|
17174
|
+
const subject = infoDict ? extractDictField(infoDict, "Subject") : null;
|
|
17175
|
+
const keywords = infoDict ? extractDictField(infoDict, "Keywords") : null;
|
|
17176
|
+
const creator = infoDict ? extractDictField(infoDict, "Creator") : null;
|
|
17177
|
+
const producer = infoDict ? extractDictField(infoDict, "Producer") : null;
|
|
17178
|
+
const creationDateRaw = infoDict ? extractDictField(infoDict, "CreationDate") : null;
|
|
17179
|
+
const modDateRaw = infoDict ? extractDictField(infoDict, "ModDate") : null;
|
|
17180
|
+
let pageCount = null;
|
|
17181
|
+
for (const b of objBlocks) {
|
|
17182
|
+
if (!/\/Type\s*\/Pages\b/.test(b[3])) continue;
|
|
17183
|
+
const countMatch = b[3].match(/\/Count\s+(\d+)/);
|
|
17184
|
+
if (countMatch) {
|
|
17185
|
+
const c = Number(countMatch[1]);
|
|
17186
|
+
if (pageCount === null || c > pageCount) pageCount = c;
|
|
17187
|
+
}
|
|
17188
|
+
}
|
|
17189
|
+
if (pageCount === null) {
|
|
17190
|
+
const pageMatches = text.match(/\/Type\s*\/Page(?!s)\b/g);
|
|
17191
|
+
if (pageMatches) pageCount = pageMatches.length;
|
|
17192
|
+
}
|
|
17193
|
+
return {
|
|
17194
|
+
version: version2,
|
|
17195
|
+
pageCount,
|
|
17196
|
+
title,
|
|
17197
|
+
author,
|
|
17198
|
+
subject,
|
|
17199
|
+
keywords,
|
|
17200
|
+
creator,
|
|
17201
|
+
producer,
|
|
17202
|
+
creationDate: creationDateRaw ? parsePdfDate(creationDateRaw) ?? creationDateRaw : null,
|
|
17203
|
+
modDate: modDateRaw ? parsePdfDate(modDateRaw) ?? modDateRaw : null,
|
|
17204
|
+
encrypted
|
|
17205
|
+
};
|
|
17206
|
+
}
|
|
17014
17207
|
|
|
17015
17208
|
// src/index.ts
|
|
17016
17209
|
var version = "0.1.0";
|
package/dist/index.d.cts
CHANGED
|
@@ -7,13 +7,13 @@ 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';
|
|
9
9
|
export { n as network } from './network-DwyAjwJS.cjs';
|
|
10
|
-
export { a as api } from './api-
|
|
10
|
+
export { a as api } from './api-Xl7OzIgq.cjs';
|
|
11
11
|
export { c as code } from './code-BUqyaofO.cjs';
|
|
12
12
|
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-D-K5aZnq.cjs';
|
|
17
17
|
|
|
18
18
|
declare const version = "0.1.0";
|
|
19
19
|
|
package/dist/index.d.ts
CHANGED
|
@@ -7,13 +7,13 @@ 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';
|
|
9
9
|
export { n as network } from './network-DwyAjwJS.js';
|
|
10
|
-
export { a as api } from './api-
|
|
10
|
+
export { a as api } from './api-Xl7OzIgq.js';
|
|
11
11
|
export { c as code } from './code-BUqyaofO.js';
|
|
12
12
|
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-D-K5aZnq.js';
|
|
17
17
|
|
|
18
18
|
declare const version = "0.1.0";
|
|
19
19
|
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { media_exports as media } from './chunk-
|
|
1
|
+
export { media_exports as media } from './chunk-WWKPLYEP.js';
|
|
2
2
|
export { units_exports as units } from './chunk-QJE743LY.js';
|
|
3
3
|
export { network_exports as network } from './chunk-V5JKVDBA.js';
|
|
4
|
-
export { api_exports as api } from './chunk-
|
|
4
|
+
export { api_exports as api } from './chunk-Q3B3YWOA.js';
|
|
5
5
|
export { code_exports as code } from './chunk-V5S6OJ4A.js';
|
|
6
6
|
export { color_exports as color } from './chunk-BPVAB4P2.js';
|
|
7
7
|
export { css_exports as css } from './chunk-6YPV2AB5.js';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
type ImageFormat = 'png' | 'jpeg' | 'gif' | 'webp' | 'bmp';
|
|
2
|
+
interface ImageInfo {
|
|
3
|
+
format: ImageFormat;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
bitDepth?: number;
|
|
7
|
+
colorType?: string;
|
|
8
|
+
hasAlpha?: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface ImageInfoError {
|
|
11
|
+
error: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Read image format, dimensions, and basic color info straight from file
|
|
15
|
+
* bytes — no decoding, no image library, no canvas. Supports PNG, JPEG,
|
|
16
|
+
* GIF, WebP, and BMP.
|
|
17
|
+
*/
|
|
18
|
+
declare function readImageInfo(bytes: Uint8Array): ImageInfo | ImageInfoError;
|
|
19
|
+
interface PdfMetadata {
|
|
20
|
+
version: string | null;
|
|
21
|
+
pageCount: number | null;
|
|
22
|
+
title: string | null;
|
|
23
|
+
author: string | null;
|
|
24
|
+
subject: string | null;
|
|
25
|
+
keywords: string | null;
|
|
26
|
+
creator: string | null;
|
|
27
|
+
producer: string | null;
|
|
28
|
+
creationDate: string | null;
|
|
29
|
+
modDate: string | null;
|
|
30
|
+
encrypted: boolean;
|
|
31
|
+
}
|
|
32
|
+
interface PdfMetadataError {
|
|
33
|
+
error: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Read PDF metadata (title, author, dates, page count, encryption flag)
|
|
37
|
+
* straight from the file's trailer/Info dictionary and page tree — no
|
|
38
|
+
* pdf.js or other PDF rendering library required.
|
|
39
|
+
*/
|
|
40
|
+
declare function readPdfMetadata(bytes: Uint8Array): PdfMetadata | PdfMetadataError;
|
|
41
|
+
|
|
42
|
+
type media_ImageFormat = ImageFormat;
|
|
43
|
+
type media_ImageInfo = ImageInfo;
|
|
44
|
+
type media_ImageInfoError = ImageInfoError;
|
|
45
|
+
type media_PdfMetadata = PdfMetadata;
|
|
46
|
+
type media_PdfMetadataError = PdfMetadataError;
|
|
47
|
+
declare const media_readImageInfo: typeof readImageInfo;
|
|
48
|
+
declare const media_readPdfMetadata: typeof readPdfMetadata;
|
|
49
|
+
declare namespace media {
|
|
50
|
+
export { 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, media_readImageInfo as readImageInfo, media_readPdfMetadata as readPdfMetadata };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { type ImageFormat as I, type PdfMetadata as P, type ImageInfo as a, type ImageInfoError as b, type PdfMetadataError as c, readPdfMetadata as d, media as m, readImageInfo as r };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
type ImageFormat = 'png' | 'jpeg' | 'gif' | 'webp' | 'bmp';
|
|
2
|
+
interface ImageInfo {
|
|
3
|
+
format: ImageFormat;
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
bitDepth?: number;
|
|
7
|
+
colorType?: string;
|
|
8
|
+
hasAlpha?: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface ImageInfoError {
|
|
11
|
+
error: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Read image format, dimensions, and basic color info straight from file
|
|
15
|
+
* bytes — no decoding, no image library, no canvas. Supports PNG, JPEG,
|
|
16
|
+
* GIF, WebP, and BMP.
|
|
17
|
+
*/
|
|
18
|
+
declare function readImageInfo(bytes: Uint8Array): ImageInfo | ImageInfoError;
|
|
19
|
+
interface PdfMetadata {
|
|
20
|
+
version: string | null;
|
|
21
|
+
pageCount: number | null;
|
|
22
|
+
title: string | null;
|
|
23
|
+
author: string | null;
|
|
24
|
+
subject: string | null;
|
|
25
|
+
keywords: string | null;
|
|
26
|
+
creator: string | null;
|
|
27
|
+
producer: string | null;
|
|
28
|
+
creationDate: string | null;
|
|
29
|
+
modDate: string | null;
|
|
30
|
+
encrypted: boolean;
|
|
31
|
+
}
|
|
32
|
+
interface PdfMetadataError {
|
|
33
|
+
error: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Read PDF metadata (title, author, dates, page count, encryption flag)
|
|
37
|
+
* straight from the file's trailer/Info dictionary and page tree — no
|
|
38
|
+
* pdf.js or other PDF rendering library required.
|
|
39
|
+
*/
|
|
40
|
+
declare function readPdfMetadata(bytes: Uint8Array): PdfMetadata | PdfMetadataError;
|
|
41
|
+
|
|
42
|
+
type media_ImageFormat = ImageFormat;
|
|
43
|
+
type media_ImageInfo = ImageInfo;
|
|
44
|
+
type media_ImageInfoError = ImageInfoError;
|
|
45
|
+
type media_PdfMetadata = PdfMetadata;
|
|
46
|
+
type media_PdfMetadataError = PdfMetadataError;
|
|
47
|
+
declare const media_readImageInfo: typeof readImageInfo;
|
|
48
|
+
declare const media_readPdfMetadata: typeof readPdfMetadata;
|
|
49
|
+
declare namespace media {
|
|
50
|
+
export { 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, media_readImageInfo as readImageInfo, media_readPdfMetadata as readPdfMetadata };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { type ImageFormat as I, type PdfMetadata as P, type ImageInfo as a, type ImageInfoError as b, type PdfMetadataError as c, readPdfMetadata as d, media as m, readImageInfo as r };
|
package/dist/tools/api.cjs
CHANGED
|
@@ -444,6 +444,55 @@ function decodeJwt(token) {
|
|
|
444
444
|
function formatJwtJson(obj) {
|
|
445
445
|
return JSON.stringify(obj, null, 2);
|
|
446
446
|
}
|
|
447
|
+
function base64urlByteLength(s) {
|
|
448
|
+
const clean = s.replace(/=+$/, "");
|
|
449
|
+
return Math.floor(clean.length * 6 / 8);
|
|
450
|
+
}
|
|
451
|
+
function parseJwks(input) {
|
|
452
|
+
const trimmed = input.trim();
|
|
453
|
+
if (!trimmed) return { ok: false, error: "No input provided" };
|
|
454
|
+
let data;
|
|
455
|
+
try {
|
|
456
|
+
data = JSON.parse(trimmed);
|
|
457
|
+
} catch (e) {
|
|
458
|
+
return { ok: false, error: `Invalid JSON: ${e instanceof Error ? e.message : String(e)}` };
|
|
459
|
+
}
|
|
460
|
+
let rawKeys;
|
|
461
|
+
if (data && typeof data === "object" && Array.isArray(data.keys)) {
|
|
462
|
+
rawKeys = data.keys;
|
|
463
|
+
} else if (data && typeof data === "object" && typeof data.kty === "string") {
|
|
464
|
+
rawKeys = [data];
|
|
465
|
+
} else {
|
|
466
|
+
return { ok: false, error: 'Input must be a JWKS object with a "keys" array, or a single JWK object with a "kty" field' };
|
|
467
|
+
}
|
|
468
|
+
const keys = rawKeys.map((k) => {
|
|
469
|
+
const key = k ?? {};
|
|
470
|
+
const kty = typeof key.kty === "string" ? key.kty : "unknown";
|
|
471
|
+
let keySize = null;
|
|
472
|
+
let curve;
|
|
473
|
+
if (kty === "RSA" && typeof key.n === "string") {
|
|
474
|
+
keySize = base64urlByteLength(key.n) * 8;
|
|
475
|
+
} else if ((kty === "EC" || kty === "OKP") && typeof key.crv === "string") {
|
|
476
|
+
curve = key.crv;
|
|
477
|
+
} else if (kty === "oct" && typeof key.k === "string") {
|
|
478
|
+
keySize = base64urlByteLength(key.k) * 8;
|
|
479
|
+
}
|
|
480
|
+
return {
|
|
481
|
+
kty,
|
|
482
|
+
use: typeof key.use === "string" ? key.use : void 0,
|
|
483
|
+
keyOps: Array.isArray(key.key_ops) ? key.key_ops.filter((x) => typeof x === "string") : void 0,
|
|
484
|
+
alg: typeof key.alg === "string" ? key.alg : void 0,
|
|
485
|
+
kid: typeof key.kid === "string" ? key.kid : void 0,
|
|
486
|
+
keySize,
|
|
487
|
+
curve,
|
|
488
|
+
raw: key
|
|
489
|
+
};
|
|
490
|
+
});
|
|
491
|
+
const kidCounts = /* @__PURE__ */ new Map();
|
|
492
|
+
for (const k of keys) if (k.kid) kidCounts.set(k.kid, (kidCounts.get(k.kid) ?? 0) + 1);
|
|
493
|
+
const duplicateKids = [...kidCounts.entries()].filter(([, c]) => c > 1).map(([kid]) => kid);
|
|
494
|
+
return { ok: true, keys, count: keys.length, duplicateKids };
|
|
495
|
+
}
|
|
447
496
|
var ALG_TO_NODE_HASH = {
|
|
448
497
|
HS256: "sha256",
|
|
449
498
|
HS384: "sha384",
|
|
@@ -1207,6 +1256,7 @@ exports.normalizeUrl = normalizeUrl;
|
|
|
1207
1256
|
exports.parseCspHeader = parseCspHeader;
|
|
1208
1257
|
exports.parseCurl = parseCurl;
|
|
1209
1258
|
exports.parseCurlCommand = parseCurlCommand;
|
|
1259
|
+
exports.parseJwks = parseJwks;
|
|
1210
1260
|
exports.parseMetaTags = parseMetaTags;
|
|
1211
1261
|
exports.parseUrl = parseUrl;
|
|
1212
1262
|
exports.removeParam = removeParam;
|
package/dist/tools/api.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { C as COMMON_HEADERS, b as COMMON_PRESETS, c as CORS_COMMON_HEADERS, d as CorsConfig, e as CorsOutput, f as CspConfig, g as CspDirective, h as CspSource, i as CurlCommand, j as CurlConfig, D as DEFAULT_CORS_CONFIG, k as DIRECTIVE_DESCRIPTIONS, l as DirectiveConfig, F as FormatResult, H as HTTP_METHODS, m as Header, n as HttpMethod, J as
|
|
1
|
+
export { C as COMMON_HEADERS, b as COMMON_PRESETS, c as CORS_COMMON_HEADERS, d as CorsConfig, e as CorsOutput, f as CspConfig, g as CspDirective, h as CspSource, i as CurlCommand, j as CurlConfig, D as DEFAULT_CORS_CONFIG, k as DIRECTIVE_DESCRIPTIONS, l as DirectiveConfig, F as FormatResult, H as HTTP_METHODS, m as Header, n as HttpMethod, J as JwkSummary, o as JwksError, p as JwksParseResult, q as JwksResult, r as JwtAlgorithm, s as JwtDecodeError, t as JwtDecodeResult, u as JwtExpiry, v as JwtPart, w as JwtResult, x as JwtSignOptions, M as MetaTags, O as OgTags, P as ParsedUrl, R as ResponseFormat, S as SUPPORTED_LANGUAGES, T as TargetLanguage, y as TwitterTags, z as addParam, A as base64urlDecode, B as base64urlEncode, E as buildCurl, G as buildCurlMultiline, I as buildUrl, K as convertToCode, L as decodeJwt, N as decodeUrlComponent, Q as detectFormat, U as encodeUrlComponent, V as extractJsonPaths, W as formatJwtJson, X as formatResponse, Y as generateCors, Z as generateCspHeader, _ as generateFullHeader, $ as generateMetaHtml, a0 as getParam, a1 as getStats, a2 as isValidUrl, a3 as normalizeUrl, a4 as parseCspHeader, a5 as parseCurl, a6 as parseCurlCommand, a7 as parseJwks, a8 as parseMetaTags, a9 as parseUrl, aa as removeParam, ab as signJwt, ac as validateCorsConfig, ad as validateCspConfig, ae as validateOgTags } from '../api-Xl7OzIgq.cjs';
|
package/dist/tools/api.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { C as COMMON_HEADERS, b as COMMON_PRESETS, c as CORS_COMMON_HEADERS, d as CorsConfig, e as CorsOutput, f as CspConfig, g as CspDirective, h as CspSource, i as CurlCommand, j as CurlConfig, D as DEFAULT_CORS_CONFIG, k as DIRECTIVE_DESCRIPTIONS, l as DirectiveConfig, F as FormatResult, H as HTTP_METHODS, m as Header, n as HttpMethod, J as
|
|
1
|
+
export { C as COMMON_HEADERS, b as COMMON_PRESETS, c as CORS_COMMON_HEADERS, d as CorsConfig, e as CorsOutput, f as CspConfig, g as CspDirective, h as CspSource, i as CurlCommand, j as CurlConfig, D as DEFAULT_CORS_CONFIG, k as DIRECTIVE_DESCRIPTIONS, l as DirectiveConfig, F as FormatResult, H as HTTP_METHODS, m as Header, n as HttpMethod, J as JwkSummary, o as JwksError, p as JwksParseResult, q as JwksResult, r as JwtAlgorithm, s as JwtDecodeError, t as JwtDecodeResult, u as JwtExpiry, v as JwtPart, w as JwtResult, x as JwtSignOptions, M as MetaTags, O as OgTags, P as ParsedUrl, R as ResponseFormat, S as SUPPORTED_LANGUAGES, T as TargetLanguage, y as TwitterTags, z as addParam, A as base64urlDecode, B as base64urlEncode, E as buildCurl, G as buildCurlMultiline, I as buildUrl, K as convertToCode, L as decodeJwt, N as decodeUrlComponent, Q as detectFormat, U as encodeUrlComponent, V as extractJsonPaths, W as formatJwtJson, X as formatResponse, Y as generateCors, Z as generateCspHeader, _ as generateFullHeader, $ as generateMetaHtml, a0 as getParam, a1 as getStats, a2 as isValidUrl, a3 as normalizeUrl, a4 as parseCspHeader, a5 as parseCurl, a6 as parseCurlCommand, a7 as parseJwks, a8 as parseMetaTags, a9 as parseUrl, aa as removeParam, ab as signJwt, ac as validateCorsConfig, ad as validateCspConfig, ae as validateOgTags } from '../api-Xl7OzIgq.js';
|
package/dist/tools/api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { COMMON_HEADERS, COMMON_PRESETS, CORS_COMMON_HEADERS, DEFAULT_CORS_CONFIG, DIRECTIVE_DESCRIPTIONS, HTTP_METHODS, SUPPORTED_LANGUAGES, addParam, base64urlDecode, base64urlEncode, buildCurl, buildCurlMultiline, buildUrl, convertToCode, decodeJwt, decodeUrlComponent, detectFormat, encodeUrlComponent, extractJsonPaths, formatJwtJson, formatResponse, generateCors, generateCspHeader, generateFullHeader, generateMetaHtml, getParam, getStats, isValidUrl, normalizeUrl, parseCspHeader, parseCurl, parseCurlCommand, parseMetaTags, parseUrl, removeParam, signJwt, validateCorsConfig, validateCspConfig, validateOgTags } from '../chunk-
|
|
1
|
+
export { COMMON_HEADERS, COMMON_PRESETS, CORS_COMMON_HEADERS, DEFAULT_CORS_CONFIG, DIRECTIVE_DESCRIPTIONS, HTTP_METHODS, SUPPORTED_LANGUAGES, addParam, base64urlDecode, base64urlEncode, buildCurl, buildCurlMultiline, buildUrl, convertToCode, decodeJwt, decodeUrlComponent, detectFormat, encodeUrlComponent, extractJsonPaths, formatJwtJson, formatResponse, generateCors, generateCspHeader, generateFullHeader, generateMetaHtml, getParam, getStats, isValidUrl, normalizeUrl, parseCspHeader, parseCurl, parseCurlCommand, parseJwks, parseMetaTags, parseUrl, removeParam, signJwt, validateCorsConfig, validateCspConfig, validateOgTags } from '../chunk-Q3B3YWOA.js';
|
|
2
2
|
import '../chunk-MLKGABMK.js';
|
package/dist/tools/media.cjs
CHANGED
|
@@ -126,5 +126,148 @@ function readImageInfo(bytes) {
|
|
|
126
126
|
}
|
|
127
127
|
return { error: "Unrecognized image format. Supported formats: PNG, JPEG, GIF, WebP, BMP" };
|
|
128
128
|
}
|
|
129
|
+
function bytesToLatin1(bytes) {
|
|
130
|
+
let out = "";
|
|
131
|
+
const CHUNK = 32768;
|
|
132
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
133
|
+
out += String.fromCharCode(...bytes.subarray(i, i + CHUNK));
|
|
134
|
+
}
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
137
|
+
function decodePdfString(raw, isHex) {
|
|
138
|
+
const bytes = [];
|
|
139
|
+
if (isHex) {
|
|
140
|
+
const hex = raw.replace(/\s+/g, "");
|
|
141
|
+
const padded = hex.length % 2 === 0 ? hex : hex + "0";
|
|
142
|
+
for (let i = 0; i < padded.length; i += 2) bytes.push(parseInt(padded.slice(i, i + 2), 16));
|
|
143
|
+
} else {
|
|
144
|
+
const s = raw.replace(/\\\r\n|\\\r|\\\n/g, "");
|
|
145
|
+
for (let i = 0; i < s.length; i++) {
|
|
146
|
+
const ch = s[i];
|
|
147
|
+
if (ch === "\\" && i + 1 < s.length) {
|
|
148
|
+
const next = s[i + 1];
|
|
149
|
+
if (next === "n") {
|
|
150
|
+
bytes.push(10);
|
|
151
|
+
i++;
|
|
152
|
+
} else if (next === "r") {
|
|
153
|
+
bytes.push(13);
|
|
154
|
+
i++;
|
|
155
|
+
} else if (next === "t") {
|
|
156
|
+
bytes.push(9);
|
|
157
|
+
i++;
|
|
158
|
+
} else if (next === "b") {
|
|
159
|
+
bytes.push(8);
|
|
160
|
+
i++;
|
|
161
|
+
} else if (next === "f") {
|
|
162
|
+
bytes.push(12);
|
|
163
|
+
i++;
|
|
164
|
+
} else if (next === "(" || next === ")" || next === "\\") {
|
|
165
|
+
bytes.push(next.charCodeAt(0));
|
|
166
|
+
i++;
|
|
167
|
+
} else if (/[0-7]/.test(next)) {
|
|
168
|
+
let oct = next;
|
|
169
|
+
i++;
|
|
170
|
+
for (let k = 0; k < 2 && i + 1 < s.length && /[0-7]/.test(s[i + 1]); k++) {
|
|
171
|
+
i++;
|
|
172
|
+
oct += s[i];
|
|
173
|
+
}
|
|
174
|
+
bytes.push(parseInt(oct, 8) & 255);
|
|
175
|
+
} else {
|
|
176
|
+
bytes.push(next.charCodeAt(0));
|
|
177
|
+
i++;
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
bytes.push(ch.charCodeAt(0) & 255);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (bytes.length >= 2 && bytes[0] === 254 && bytes[1] === 255) {
|
|
185
|
+
let out = "";
|
|
186
|
+
for (let i = 2; i + 1 < bytes.length; i += 2) out += String.fromCharCode(bytes[i] << 8 | bytes[i + 1]);
|
|
187
|
+
return out;
|
|
188
|
+
}
|
|
189
|
+
return bytes.map((b) => String.fromCharCode(b)).join("");
|
|
190
|
+
}
|
|
191
|
+
function extractDictField(dict, key) {
|
|
192
|
+
const litMatch = dict.match(new RegExp(`/${key}\\s*\\(((?:\\\\.|[^\\\\()])*)\\)`));
|
|
193
|
+
if (litMatch) return decodePdfString(litMatch[1], false);
|
|
194
|
+
const hexMatch = dict.match(new RegExp(`/${key}\\s*<([0-9A-Fa-f\\s]*)>`));
|
|
195
|
+
if (hexMatch) return decodePdfString(hexMatch[1], true);
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
function findObject(text, objNum, gen) {
|
|
199
|
+
const m = text.match(new RegExp(`(?:^|[^0-9])${objNum}\\s+${gen}\\s+obj([\\s\\S]*?)endobj`));
|
|
200
|
+
return m ? m[1] : null;
|
|
201
|
+
}
|
|
202
|
+
function parsePdfDate(raw) {
|
|
203
|
+
const m = raw.match(/^D:(\d{4})(\d{2})?(\d{2})?(\d{2})?(\d{2})?(\d{2})?([Z+-])?(\d{2})?'?(\d{2})?'?/);
|
|
204
|
+
if (!m) return null;
|
|
205
|
+
const [, y, mo = "01", d = "01", h = "00", mi = "00", s = "00", tz, tzh, tzm] = m;
|
|
206
|
+
let iso = `${y}-${mo}-${d}T${h}:${mi}:${s}`;
|
|
207
|
+
if (tz === "Z") iso += "Z";
|
|
208
|
+
else if (tz === "+" || tz === "-") iso += `${tz}${tzh ?? "00"}:${tzm ?? "00"}`;
|
|
209
|
+
return iso;
|
|
210
|
+
}
|
|
211
|
+
function readPdfMetadata(bytes) {
|
|
212
|
+
if (bytes.length < 8) return { error: "File too small to be a PDF" };
|
|
213
|
+
const header = bytesToLatin1(bytes.subarray(0, 16));
|
|
214
|
+
const versionMatch = header.match(/%PDF-(\d\.\d)/);
|
|
215
|
+
if (!versionMatch) return { error: "Not a valid PDF file (missing %PDF header)" };
|
|
216
|
+
const version = versionMatch[1];
|
|
217
|
+
const text = bytesToLatin1(bytes);
|
|
218
|
+
const trailerMatches = [...text.matchAll(/trailer\s*<<([\s\S]*?)>>/g)];
|
|
219
|
+
let infoDict = null;
|
|
220
|
+
let encrypted = false;
|
|
221
|
+
if (trailerMatches.length > 0) {
|
|
222
|
+
const trailer = trailerMatches[trailerMatches.length - 1][1];
|
|
223
|
+
encrypted = /\/Encrypt\s+\d+\s+\d+\s+R/.test(trailer);
|
|
224
|
+
const infoRef = trailer.match(/\/Info\s+(\d+)\s+(\d+)\s+R/);
|
|
225
|
+
if (infoRef) infoDict = findObject(text, Number(infoRef[1]), Number(infoRef[2]));
|
|
226
|
+
}
|
|
227
|
+
const objBlocks = [...text.matchAll(/(\d+)\s+(\d+)\s+obj([\s\S]*?)endobj/g)];
|
|
228
|
+
if (!infoDict) {
|
|
229
|
+
for (const b of objBlocks) {
|
|
230
|
+
if (/\/(Title|Author|Producer|Creator|CreationDate)\b/.test(b[3]) && !/\/Type\s*\/(Page|Pages|Catalog|Font)\b/.test(b[3])) {
|
|
231
|
+
infoDict = b[3];
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const title = infoDict ? extractDictField(infoDict, "Title") : null;
|
|
237
|
+
const author = infoDict ? extractDictField(infoDict, "Author") : null;
|
|
238
|
+
const subject = infoDict ? extractDictField(infoDict, "Subject") : null;
|
|
239
|
+
const keywords = infoDict ? extractDictField(infoDict, "Keywords") : null;
|
|
240
|
+
const creator = infoDict ? extractDictField(infoDict, "Creator") : null;
|
|
241
|
+
const producer = infoDict ? extractDictField(infoDict, "Producer") : null;
|
|
242
|
+
const creationDateRaw = infoDict ? extractDictField(infoDict, "CreationDate") : null;
|
|
243
|
+
const modDateRaw = infoDict ? extractDictField(infoDict, "ModDate") : null;
|
|
244
|
+
let pageCount = null;
|
|
245
|
+
for (const b of objBlocks) {
|
|
246
|
+
if (!/\/Type\s*\/Pages\b/.test(b[3])) continue;
|
|
247
|
+
const countMatch = b[3].match(/\/Count\s+(\d+)/);
|
|
248
|
+
if (countMatch) {
|
|
249
|
+
const c = Number(countMatch[1]);
|
|
250
|
+
if (pageCount === null || c > pageCount) pageCount = c;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (pageCount === null) {
|
|
254
|
+
const pageMatches = text.match(/\/Type\s*\/Page(?!s)\b/g);
|
|
255
|
+
if (pageMatches) pageCount = pageMatches.length;
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
version,
|
|
259
|
+
pageCount,
|
|
260
|
+
title,
|
|
261
|
+
author,
|
|
262
|
+
subject,
|
|
263
|
+
keywords,
|
|
264
|
+
creator,
|
|
265
|
+
producer,
|
|
266
|
+
creationDate: creationDateRaw ? parsePdfDate(creationDateRaw) ?? creationDateRaw : null,
|
|
267
|
+
modDate: modDateRaw ? parsePdfDate(modDateRaw) ?? modDateRaw : null,
|
|
268
|
+
encrypted
|
|
269
|
+
};
|
|
270
|
+
}
|
|
129
271
|
|
|
130
272
|
exports.readImageInfo = readImageInfo;
|
|
273
|
+
exports.readPdfMetadata = readPdfMetadata;
|
package/dist/tools/media.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { I as ImageFormat, a as ImageInfo, b as ImageInfoError, r as readImageInfo } from '../media-
|
|
1
|
+
export { I as ImageFormat, a as ImageInfo, b as ImageInfoError, P as PdfMetadata, c as PdfMetadataError, r as readImageInfo, d as readPdfMetadata } from '../media-D-K5aZnq.cjs';
|
package/dist/tools/media.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { I as ImageFormat, a as ImageInfo, b as ImageInfoError, r as readImageInfo } from '../media-
|
|
1
|
+
export { I as ImageFormat, a as ImageInfo, b as ImageInfoError, P as PdfMetadata, c as PdfMetadataError, r as readImageInfo, d as readPdfMetadata } from '../media-D-K5aZnq.js';
|
package/dist/tools/media.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { readImageInfo } from '../chunk-
|
|
1
|
+
export { readImageInfo, readPdfMetadata } from '../chunk-WWKPLYEP.js';
|
|
2
2
|
import '../chunk-MLKGABMK.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@utilix-tech/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "140+ 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",
|