@utilix-tech/sdk 0.41.0 → 0.43.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.
@@ -969,6 +969,118 @@ Output: ${e.output.trim()}`).join("\n\n");
969
969
  }
970
970
  return { formatted, exampleCount: valid.length, format };
971
971
  }
972
+ var TOOL_NAME_RE = /^[a-zA-Z0-9_-]{1,64}$/;
973
+ function normalizeToolDefs(data) {
974
+ let rawList;
975
+ if (Array.isArray(data)) {
976
+ rawList = data;
977
+ } else if (data && typeof data === "object" && Array.isArray(data.tools)) {
978
+ rawList = data.tools;
979
+ } else {
980
+ rawList = [data];
981
+ }
982
+ const out = [];
983
+ for (const item of rawList) {
984
+ if (!item || typeof item !== "object") {
985
+ return { error: "Each tool definition must be a JSON object" };
986
+ }
987
+ const obj = item;
988
+ if (obj.type === "function" && obj.function && typeof obj.function === "object") {
989
+ const fn = obj.function;
990
+ out.push({ name: String(fn.name ?? ""), description: typeof fn.description === "string" ? fn.description : void 0, schema: fn.parameters, format: "openai" });
991
+ } else if ("input_schema" in obj) {
992
+ out.push({ name: String(obj.name ?? ""), description: typeof obj.description === "string" ? obj.description : void 0, schema: obj.input_schema, format: "anthropic" });
993
+ } else if ("inputSchema" in obj) {
994
+ out.push({ name: String(obj.name ?? ""), description: typeof obj.description === "string" ? obj.description : void 0, schema: obj.inputSchema, format: "mcp" });
995
+ } else if ("parameters" in obj || "name" in obj) {
996
+ out.push({ name: String(obj.name ?? ""), description: typeof obj.description === "string" ? obj.description : void 0, schema: obj.parameters, format: "bare" });
997
+ } else {
998
+ return { error: 'Unrecognized tool-definition format: expected an OpenAI ({type:"function",function:{...}}), Anthropic ({name,input_schema}), or MCP ({name,inputSchema}) shape' };
999
+ }
1000
+ }
1001
+ return out;
1002
+ }
1003
+ function lintToolSchema(jsonText) {
1004
+ if (!jsonText || !jsonText.trim()) return { error: "Input is empty" };
1005
+ let data;
1006
+ try {
1007
+ data = JSON.parse(jsonText);
1008
+ } catch (e) {
1009
+ return { error: `Invalid JSON: ${e.message}` };
1010
+ }
1011
+ const normalized = normalizeToolDefs(data);
1012
+ if ("error" in normalized) return normalized;
1013
+ if (normalized.length === 0) return { error: "No tool definitions found" };
1014
+ const issues = [];
1015
+ const seenNames = /* @__PURE__ */ new Map();
1016
+ for (const tool of normalized) {
1017
+ const label = tool.name || "(unnamed)";
1018
+ seenNames.set(label, (seenNames.get(label) ?? 0) + 1);
1019
+ if (!tool.name) {
1020
+ issues.push({ severity: "error", tool: label, path: "name", message: 'Tool is missing a "name"' });
1021
+ } else if (!TOOL_NAME_RE.test(tool.name)) {
1022
+ issues.push({ severity: "error", tool: label, path: "name", message: `Tool name "${tool.name}" must match ^[a-zA-Z0-9_-]{1,64}$ (letters, digits, underscores, hyphens, max 64 chars) to be accepted by OpenAI/Anthropic function calling` });
1023
+ }
1024
+ if (!tool.description || !tool.description.trim()) {
1025
+ issues.push({ severity: "error", tool: label, path: "description", message: 'Tool is missing a "description" \u2014 the model relies entirely on this text to decide when to call it' });
1026
+ } else {
1027
+ if (tool.description.trim().length < 10) {
1028
+ issues.push({ severity: "warning", tool: label, path: "description", message: "Description is very short; a vague description measurably hurts the model's ability to pick the right tool" });
1029
+ }
1030
+ if (tool.description.length > 1024) {
1031
+ issues.push({ severity: "warning", tool: label, path: "description", message: `Description is ${tool.description.length} characters; long descriptions cost tokens on every request that includes this tool` });
1032
+ }
1033
+ }
1034
+ if (tool.schema === void 0 || tool.schema === null) {
1035
+ issues.push({ severity: "warning", tool: label, path: "parameters", message: "Tool has no parameter schema; only correct if the tool genuinely takes no arguments" });
1036
+ continue;
1037
+ }
1038
+ if (typeof tool.schema !== "object" || Array.isArray(tool.schema)) {
1039
+ issues.push({ severity: "error", tool: label, path: "parameters", message: "Parameter schema must be a JSON Schema object" });
1040
+ continue;
1041
+ }
1042
+ const schema = tool.schema;
1043
+ if (schema.type !== void 0 && schema.type !== "object") {
1044
+ issues.push({ severity: "error", tool: label, path: "parameters.type", message: `Top-level parameter schema type is "${String(schema.type)}"; OpenAI and Anthropic both require "object" at the top level` });
1045
+ }
1046
+ const properties = schema.properties;
1047
+ if (properties !== void 0 && (typeof properties !== "object" || properties === null || Array.isArray(properties))) {
1048
+ issues.push({ severity: "error", tool: label, path: "parameters.properties", message: '"properties" must be an object' });
1049
+ } else if (properties && typeof properties === "object") {
1050
+ const propsObj = properties;
1051
+ const propNames = Object.keys(propsObj);
1052
+ for (const propName of propNames) {
1053
+ const prop = propsObj[propName];
1054
+ const propPath = `parameters.properties.${propName}`;
1055
+ if (!prop || typeof prop !== "object") {
1056
+ issues.push({ severity: "error", tool: label, path: propPath, message: "Property schema must be an object" });
1057
+ continue;
1058
+ }
1059
+ const propObj = prop;
1060
+ if (!propObj.description) {
1061
+ issues.push({ severity: "warning", tool: label, path: propPath, message: `Property "${propName}" has no description; missing per-parameter descriptions measurably hurt model accuracy on which value to pass` });
1062
+ }
1063
+ if (Array.isArray(propObj.enum) && propObj.enum.length === 0) {
1064
+ issues.push({ severity: "error", tool: label, path: propPath, message: `Property "${propName}" has an empty "enum" array` });
1065
+ }
1066
+ }
1067
+ if (Array.isArray(schema.required)) {
1068
+ for (const req of schema.required) {
1069
+ if (typeof req === "string" && !propNames.includes(req)) {
1070
+ issues.push({ severity: "error", tool: label, path: "parameters.required", message: `"required" lists "${req}", which isn't defined in "properties"` });
1071
+ }
1072
+ }
1073
+ }
1074
+ }
1075
+ }
1076
+ for (const [name, count] of seenNames) {
1077
+ if (count > 1 && name !== "(unnamed)") {
1078
+ issues.push({ severity: "error", tool: name, path: "name", message: `Tool name "${name}" is used ${count} times; tool names must be unique within a single request` });
1079
+ }
1080
+ }
1081
+ const valid = !issues.some((i) => i.severity === "error");
1082
+ return { toolCount: normalized.length, issues, valid };
1083
+ }
972
1084
 
973
1085
  exports.MODEL_PRICING = MODEL_PRICING;
974
1086
  exports.chunkText = chunkText;
@@ -990,6 +1102,7 @@ exports.extractTables = extractTables;
990
1102
  exports.extractUrls = extractUrls;
991
1103
  exports.flattenJson = flattenJson;
992
1104
  exports.formatFewShotExamples = formatFewShotExamples;
1105
+ exports.lintToolSchema = lintToolSchema;
993
1106
  exports.mergeJson = mergeJson;
994
1107
  exports.redactPii = redactPii;
995
1108
  exports.repairJson = repairJson;
@@ -1 +1 @@
1
- export { C as ChunkStrategy, b as CompressHtmlResult, c as CompressJsonResult, d as CompressMarkdownResult, e as CostEstimate, D as DedupeResult, f as DedupeStrategy, g as DiffEntry2, h as DiffOp2, i as DiffResult2, E as Entity2, j as EntityType2, k as ExtractJsonResult, l as ExtractKeywordsResult, m as ExtractUrlsResult, F as FewShotExample, n as FewShotFormat, o as FewShotFormatResult, I as InjectionDetectResult, p as InjectionFinding, J as JsonBlock, q as JsonRepairResult, K as Keyword, M as MODEL_PRICING, r as MergeResult, s as MergeStrategy, t as ModelPricing, P as PiiDetectResult, u as PiiFinding, v as PiiType, R as RankedChunk, w as RelevanceResult, S as SanitizeResult, x as SecretDetectResult, y as SecretFinding, z as SecretType, A as SummaryResult, T as TableResult2, B as TextChunk, G as TokenEstimate, H as TokenEstimateResult, L as TrimResult, N as TrimStrategy, U as UrlMatch, V as ValidationError, O as ValidationResult, Q as VectorSimilarityResult, W as chunkText, X as compressHtml, Y as compressJson, Z as compressMarkdown, _ as deduplicateLines, $ as detectPii, a0 as detectPromptInjection, a1 as detectSecrets, a2 as diffJson, a3 as estimateCost, a4 as estimateTokens, a5 as expandQuery, a6 as extractEntities, a7 as extractJson, a8 as extractKeywords, a9 as extractTables, aa as extractUrls, ab as flattenJson, ac as formatFewShotExamples, ad as mergeJson, ae as redactPii, af as repairJson, ag as rerankChunks, ah as sanitizeHtml, ai as scoreRelevance, aj as summarizeForLlm, ak as trimToTokens, al as unflattenJson, am as validateJsonSchema, an as vectorSimilarity } from '../ai_agent-C1zudGgT.cjs';
1
+ export { C as ChunkStrategy, b as CompressHtmlResult, c as CompressJsonResult, d as CompressMarkdownResult, e as CostEstimate, D as DedupeResult, f as DedupeStrategy, g as DiffEntry2, h as DiffOp2, i as DiffResult2, E as Entity2, j as EntityType2, k as ExtractJsonResult, l as ExtractKeywordsResult, m as ExtractUrlsResult, F as FewShotExample, n as FewShotFormat, o as FewShotFormatResult, I as InjectionDetectResult, p as InjectionFinding, J as JsonBlock, q as JsonRepairResult, K as Keyword, M as MODEL_PRICING, r as MergeResult, s as MergeStrategy, t as ModelPricing, P as PiiDetectResult, u as PiiFinding, v as PiiType, R as RankedChunk, w as RelevanceResult, S as SanitizeResult, x as SecretDetectResult, y as SecretFinding, z as SecretType, A as SummaryResult, T as TableResult2, B as TextChunk, G as TokenEstimate, H as TokenEstimateResult, L as ToolSchemaIssue, N as ToolSchemaLintResult, O as TrimResult, Q as TrimStrategy, U as UrlMatch, V as ValidationError, W as ValidationResult, X as VectorSimilarityResult, Y as chunkText, Z as compressHtml, _ as compressJson, $ as compressMarkdown, a0 as deduplicateLines, a1 as detectPii, a2 as detectPromptInjection, a3 as detectSecrets, a4 as diffJson, a5 as estimateCost, a6 as estimateTokens, a7 as expandQuery, a8 as extractEntities, a9 as extractJson, aa as extractKeywords, ab as extractTables, ac as extractUrls, ad as flattenJson, ae as formatFewShotExamples, af as lintToolSchema, ag as mergeJson, ah as redactPii, ai as repairJson, aj as rerankChunks, ak as sanitizeHtml, al as scoreRelevance, am as summarizeForLlm, an as trimToTokens, ao as unflattenJson, ap as validateJsonSchema, aq as vectorSimilarity } from '../ai_agent-CmrVjvYH.cjs';
@@ -1 +1 @@
1
- export { C as ChunkStrategy, b as CompressHtmlResult, c as CompressJsonResult, d as CompressMarkdownResult, e as CostEstimate, D as DedupeResult, f as DedupeStrategy, g as DiffEntry2, h as DiffOp2, i as DiffResult2, E as Entity2, j as EntityType2, k as ExtractJsonResult, l as ExtractKeywordsResult, m as ExtractUrlsResult, F as FewShotExample, n as FewShotFormat, o as FewShotFormatResult, I as InjectionDetectResult, p as InjectionFinding, J as JsonBlock, q as JsonRepairResult, K as Keyword, M as MODEL_PRICING, r as MergeResult, s as MergeStrategy, t as ModelPricing, P as PiiDetectResult, u as PiiFinding, v as PiiType, R as RankedChunk, w as RelevanceResult, S as SanitizeResult, x as SecretDetectResult, y as SecretFinding, z as SecretType, A as SummaryResult, T as TableResult2, B as TextChunk, G as TokenEstimate, H as TokenEstimateResult, L as TrimResult, N as TrimStrategy, U as UrlMatch, V as ValidationError, O as ValidationResult, Q as VectorSimilarityResult, W as chunkText, X as compressHtml, Y as compressJson, Z as compressMarkdown, _ as deduplicateLines, $ as detectPii, a0 as detectPromptInjection, a1 as detectSecrets, a2 as diffJson, a3 as estimateCost, a4 as estimateTokens, a5 as expandQuery, a6 as extractEntities, a7 as extractJson, a8 as extractKeywords, a9 as extractTables, aa as extractUrls, ab as flattenJson, ac as formatFewShotExamples, ad as mergeJson, ae as redactPii, af as repairJson, ag as rerankChunks, ah as sanitizeHtml, ai as scoreRelevance, aj as summarizeForLlm, ak as trimToTokens, al as unflattenJson, am as validateJsonSchema, an as vectorSimilarity } from '../ai_agent-C1zudGgT.js';
1
+ export { C as ChunkStrategy, b as CompressHtmlResult, c as CompressJsonResult, d as CompressMarkdownResult, e as CostEstimate, D as DedupeResult, f as DedupeStrategy, g as DiffEntry2, h as DiffOp2, i as DiffResult2, E as Entity2, j as EntityType2, k as ExtractJsonResult, l as ExtractKeywordsResult, m as ExtractUrlsResult, F as FewShotExample, n as FewShotFormat, o as FewShotFormatResult, I as InjectionDetectResult, p as InjectionFinding, J as JsonBlock, q as JsonRepairResult, K as Keyword, M as MODEL_PRICING, r as MergeResult, s as MergeStrategy, t as ModelPricing, P as PiiDetectResult, u as PiiFinding, v as PiiType, R as RankedChunk, w as RelevanceResult, S as SanitizeResult, x as SecretDetectResult, y as SecretFinding, z as SecretType, A as SummaryResult, T as TableResult2, B as TextChunk, G as TokenEstimate, H as TokenEstimateResult, L as ToolSchemaIssue, N as ToolSchemaLintResult, O as TrimResult, Q as TrimStrategy, U as UrlMatch, V as ValidationError, W as ValidationResult, X as VectorSimilarityResult, Y as chunkText, Z as compressHtml, _ as compressJson, $ as compressMarkdown, a0 as deduplicateLines, a1 as detectPii, a2 as detectPromptInjection, a3 as detectSecrets, a4 as diffJson, a5 as estimateCost, a6 as estimateTokens, a7 as expandQuery, a8 as extractEntities, a9 as extractJson, aa as extractKeywords, ab as extractTables, ac as extractUrls, ad as flattenJson, ae as formatFewShotExamples, af as lintToolSchema, ag as mergeJson, ah as redactPii, ai as repairJson, aj as rerankChunks, ak as sanitizeHtml, al as scoreRelevance, am as summarizeForLlm, an as trimToTokens, ao as unflattenJson, ap as validateJsonSchema, aq as vectorSimilarity } from '../ai_agent-CmrVjvYH.js';
@@ -1,2 +1,2 @@
1
- export { MODEL_PRICING, chunkText, compressHtml, compressJson, compressMarkdown, deduplicateLines, detectPii, detectPromptInjection, detectSecrets, diffJson, estimateCost, estimateTokens, expandQuery, extractEntities, extractJson, extractKeywords, extractTables, extractUrls, flattenJson, formatFewShotExamples, mergeJson, redactPii, repairJson, rerankChunks, sanitizeHtml, scoreRelevance, summarizeForLlm, trimToTokens, unflattenJson, validateJsonSchema, vectorSimilarity } from '../chunk-W3J7GZVQ.js';
1
+ export { MODEL_PRICING, chunkText, compressHtml, compressJson, compressMarkdown, deduplicateLines, detectPii, detectPromptInjection, detectSecrets, diffJson, estimateCost, estimateTokens, expandQuery, extractEntities, extractJson, extractKeywords, extractTables, extractUrls, flattenJson, formatFewShotExamples, lintToolSchema, mergeJson, redactPii, repairJson, rerankChunks, sanitizeHtml, scoreRelevance, summarizeForLlm, trimToTokens, unflattenJson, validateJsonSchema, vectorSimilarity } from '../chunk-EKIXOA7B.js';
2
2
  import '../chunk-MLKGABMK.js';
@@ -2278,6 +2278,150 @@ function parseContentRangeHeader(header) {
2278
2278
  }
2279
2279
  return { unit, start, end, total, isUnsatisfiable, isTotalUnknown, byteLength: end - start + 1 };
2280
2280
  }
2281
+ var VARY_HEADER_NOTES = {
2282
+ "accept-encoding": "Caches must store a separate response per compression scheme (gzip, br, etc.) the client accepts.",
2283
+ "accept-language": "Caches must store a separate response per requested language, which can fragment a shared cache badly if Accept-Language values are highly varied.",
2284
+ "accept": "Caches must store a separate response per requested content type (e.g. JSON vs HTML).",
2285
+ "user-agent": "Caches must store a separate response per distinct User-Agent string, which is often unique enough to make caching nearly ineffective.",
2286
+ "authorization": "Signals the response is user-specific; most shared caches will refuse to cache it at all rather than key on this header.",
2287
+ "cookie": "Same effect as Authorization: shared caches typically treat the response as private and skip caching rather than key on cookie values.",
2288
+ "origin": "Caches must store a separate response per requesting Origin, needed whenever a response includes CORS headers that differ by origin.",
2289
+ "x-requested-with": "Caches must store a separate response depending on whether the request was made via an XHR/fetch client hint.",
2290
+ "x-forwarded-proto": "Caches must store a separate response for HTTP vs HTTPS requests, relevant behind a proxy or load balancer that terminates TLS."
2291
+ };
2292
+ function buildVaryHeader(headers) {
2293
+ if (!Array.isArray(headers) || headers.length === 0) return { error: "At least one header is required" };
2294
+ const trimmed = headers.map((h) => typeof h === "string" ? h.trim() : "").filter((h) => h.length > 0);
2295
+ if (trimmed.length === 0) return { error: "At least one header is required" };
2296
+ const warnings = [];
2297
+ if (trimmed.some((h) => h === "*") && trimmed.length > 1) {
2298
+ warnings.push('"*" makes every request effectively uncacheable; combining it with other header names is redundant, most caches will just skip caching entirely');
2299
+ }
2300
+ const seen = /* @__PURE__ */ new Map();
2301
+ for (const h of trimmed) {
2302
+ const key = h.toLowerCase();
2303
+ if (!seen.has(key)) seen.set(key, h);
2304
+ }
2305
+ if (seen.size < trimmed.length) warnings.push("duplicate header names were removed");
2306
+ const entries = Array.from(seen.values()).map((h) => ({
2307
+ header: h,
2308
+ note: h === "*" ? "Every response is considered unique; most caches will not store it at all." : VARY_HEADER_NOTES[h.toLowerCase()] ?? `Caches must store a separate response per distinct ${h} value.`
2309
+ }));
2310
+ const headerValue = entries.map((e) => e.header).join(", ");
2311
+ return { header: `Vary: ${headerValue}`, headerValue, entries, warnings };
2312
+ }
2313
+ function parseVaryHeader(raw) {
2314
+ if (!raw || raw.trim() === "") return { error: "Input is empty" };
2315
+ const withoutLabel = raw.trim().replace(/^vary:\s*/i, "");
2316
+ const headers = withoutLabel.split(",").map((h) => h.trim()).filter((h) => h.length > 0);
2317
+ return buildVaryHeader(headers);
2318
+ }
2319
+ var VALID_MANIFEST_DISPLAY = /* @__PURE__ */ new Set(["fullscreen", "standalone", "minimal-ui", "browser"]);
2320
+ function validateManifest(jsonText) {
2321
+ if (!jsonText || !jsonText.trim()) return { error: "Input is empty" };
2322
+ let manifest;
2323
+ try {
2324
+ manifest = JSON.parse(jsonText);
2325
+ } catch (e) {
2326
+ return { error: `Invalid JSON: ${e.message}` };
2327
+ }
2328
+ if (typeof manifest !== "object" || manifest === null || Array.isArray(manifest)) {
2329
+ return { error: "Manifest must be a JSON object" };
2330
+ }
2331
+ const m = manifest;
2332
+ const issues = [];
2333
+ if (!m.name && !m.short_name) {
2334
+ issues.push({ severity: "error", path: "name", message: 'Manifest must have at least one of "name" or "short_name"' });
2335
+ }
2336
+ if (m.name !== void 0 && typeof m.name !== "string") {
2337
+ issues.push({ severity: "error", path: "name", message: '"name" must be a string' });
2338
+ } else if (typeof m.name === "string" && m.name.length > 45) {
2339
+ issues.push({ severity: "warning", path: "name", message: `"name" is ${m.name.length} characters; keep it under ~45 to avoid truncation in install prompts` });
2340
+ }
2341
+ if (m.short_name !== void 0 && typeof m.short_name !== "string") {
2342
+ issues.push({ severity: "error", path: "short_name", message: '"short_name" must be a string' });
2343
+ } else if (typeof m.short_name === "string" && m.short_name.length > 12) {
2344
+ issues.push({ severity: "warning", path: "short_name", message: `"short_name" is ${m.short_name.length} characters; keep it under ~12 to avoid truncation on home screens` });
2345
+ }
2346
+ if (!m.start_url) {
2347
+ issues.push({ severity: "error", path: "start_url", message: 'Manifest is missing "start_url"' });
2348
+ } else if (typeof m.start_url !== "string") {
2349
+ issues.push({ severity: "error", path: "start_url", message: '"start_url" must be a string' });
2350
+ } else if (m.start_url.startsWith("//")) {
2351
+ issues.push({ severity: "warning", path: "start_url", message: '"start_url" looks protocol-relative; use a relative path (e.g. "/") or a full absolute URL instead' });
2352
+ }
2353
+ if (m.display !== void 0) {
2354
+ if (typeof m.display !== "string" || !VALID_MANIFEST_DISPLAY.has(m.display)) {
2355
+ issues.push({ severity: "error", path: "display", message: `"display" must be one of: ${[...VALID_MANIFEST_DISPLAY].join(", ")}` });
2356
+ }
2357
+ } else {
2358
+ issues.push({ severity: "warning", path: "display", message: 'Missing "display"; it defaults to "browser", which will not open the installed app in its own standalone window' });
2359
+ }
2360
+ const icons = [];
2361
+ let hasMaskableIcon = false;
2362
+ let has512Icon = false;
2363
+ if (!Array.isArray(m.icons) || m.icons.length === 0) {
2364
+ issues.push({ severity: "error", path: "icons", message: 'Manifest must have a non-empty "icons" array' });
2365
+ } else {
2366
+ m.icons.forEach((icon, i) => {
2367
+ const path = `icons[${i}]`;
2368
+ if (!icon || typeof icon !== "object") {
2369
+ issues.push({ severity: "error", path, message: "Icon entry must be an object" });
2370
+ return;
2371
+ }
2372
+ const iconObj = icon;
2373
+ if (!iconObj.src || typeof iconObj.src !== "string") {
2374
+ issues.push({ severity: "error", path, message: 'Icon entry is missing a required "src"' });
2375
+ }
2376
+ if (iconObj.sizes !== void 0) {
2377
+ if (typeof iconObj.sizes !== "string" || iconObj.sizes !== "any" && !/^\d+x\d+(\s+\d+x\d+)*$/i.test(iconObj.sizes)) {
2378
+ issues.push({ severity: "warning", path, message: `"sizes" value "${String(iconObj.sizes)}" doesn't match the expected "WIDTHxHEIGHT" format` });
2379
+ } else if (/(^|\s)512x512(\s|$)/i.test(iconObj.sizes)) {
2380
+ has512Icon = true;
2381
+ }
2382
+ }
2383
+ if (typeof iconObj.purpose === "string" && iconObj.purpose.toLowerCase().includes("maskable")) {
2384
+ hasMaskableIcon = true;
2385
+ }
2386
+ icons.push({
2387
+ src: typeof iconObj.src === "string" ? iconObj.src : "",
2388
+ sizes: typeof iconObj.sizes === "string" ? iconObj.sizes : void 0,
2389
+ type: typeof iconObj.type === "string" ? iconObj.type : void 0,
2390
+ purpose: typeof iconObj.purpose === "string" ? iconObj.purpose : void 0
2391
+ });
2392
+ });
2393
+ if (icons.length > 0) {
2394
+ if (!has512Icon) {
2395
+ issues.push({ severity: "warning", path: "icons", message: "No icon sized 512x512 found; this size is used for splash screens and app store listings" });
2396
+ }
2397
+ if (!hasMaskableIcon) {
2398
+ issues.push({ severity: "warning", path: "icons", message: 'No icon with purpose "maskable" (or "any maskable") found; without one, Android may crop your icon into its adaptive icon mask' });
2399
+ }
2400
+ }
2401
+ }
2402
+ if (m.theme_color !== void 0 && typeof m.theme_color !== "string") {
2403
+ issues.push({ severity: "error", path: "theme_color", message: '"theme_color" must be a CSS color string' });
2404
+ }
2405
+ if (m.background_color !== void 0 && typeof m.background_color !== "string") {
2406
+ issues.push({ severity: "error", path: "background_color", message: '"background_color" must be a CSS color string' });
2407
+ } else if (m.background_color === void 0) {
2408
+ issues.push({ severity: "warning", path: "background_color", message: 'Missing "background_color"; without it the splash screen background defaults to white' });
2409
+ }
2410
+ const valid = !issues.some((i) => i.severity === "error");
2411
+ return {
2412
+ issues,
2413
+ valid,
2414
+ summary: {
2415
+ name: typeof m.name === "string" ? m.name : void 0,
2416
+ shortName: typeof m.short_name === "string" ? m.short_name : void 0,
2417
+ startUrl: typeof m.start_url === "string" ? m.start_url : void 0,
2418
+ display: typeof m.display === "string" ? m.display : void 0,
2419
+ icons,
2420
+ hasMaskableIcon,
2421
+ has512Icon
2422
+ }
2423
+ };
2424
+ }
2281
2425
 
2282
2426
  exports.DNS_RECORD_TYPES = DNS_RECORD_TYPES;
2283
2427
  exports.HTTP_HEADERS = HTTP_HEADERS;
@@ -2292,6 +2436,7 @@ exports.buildLinkHeader = buildLinkHeader;
2292
2436
  exports.buildMapUrl = buildMapUrl;
2293
2437
  exports.buildRangeHeader = buildRangeHeader;
2294
2438
  exports.buildReferrerPolicy = buildReferrerPolicy;
2439
+ exports.buildVaryHeader = buildVaryHeader;
2295
2440
  exports.checkSetCookieHeader = checkSetCookieHeader;
2296
2441
  exports.countryCodeToFlag = countryCodeToFlag;
2297
2442
  exports.formatCoordinates = formatCoordinates;
@@ -2313,6 +2458,7 @@ exports.parseGeoResponse = parseGeoResponse;
2313
2458
  exports.parseHar = parseHar;
2314
2459
  exports.parseIpv6Address = parseIpv6Address;
2315
2460
  exports.parseUserAgent = parseUserAgent;
2461
+ exports.parseVaryHeader = parseVaryHeader;
2316
2462
  exports.searchHeaders = searchHeaders;
2317
2463
  exports.searchStatusCodes = searchStatusCodes;
2318
2464
  exports.statusCodeToText = statusCodeToText;
@@ -2320,5 +2466,6 @@ exports.typeNumberToLabel = typeNumberToLabel;
2320
2466
  exports.validateDomain = validateDomain;
2321
2467
  exports.validateHeaderName = validateHeaderName;
2322
2468
  exports.validateHeaderValue = validateHeaderValue;
2469
+ exports.validateManifest = validateManifest;
2323
2470
  exports.validateRobotsTxt = validateRobotsTxt;
2324
2471
  exports.validateSitemap = validateSitemap;
@@ -1 +1 @@
1
- export { A as AuthResultEntry, B as BuildRangeHeaderOptions, C as CacheControlDirective, a as CacheControlOptions, b as CacheControlResult, c as ContentRangeResult, d as CookieAttributes, e as CookieCheckResult, D as DNS_RECORD_TYPES, f as DnsRecord, g as DnsRecordType, h as DnsResponse, E as EmailHeaderAnalysis, i as EmailHeaderField, G as GeoResult, H as HTTP_HEADERS, j as HarEntry, k as HarParseResult, l as HarSummary, m as HeaderCategory, o as HttpHeader, I as Ipv6AddressType, p as Ipv6ParseResult, L as LINK_REL_VALUES, q as LinkHeaderEntry, r as LinkHeaderEntryInput, s as LinkHeaderResult, t as LinkRel, P as ParsedDnsResult, u as ParsedGeoResult, R as REFERRER_POLICY_VALUES, v as RangeEntry, w as RangeEntryInput, x as RangeHeaderResult, y as ReceivedHop, z as ReferrerPolicyEntry, F as ReferrerPolicyResult, J as ReferrerPolicyValue, K as RobotsGroup, M as RobotsIssue, N as RobotsRule, O as RobotsValidationResult, S as STATUS_CODES, Q as SameSiteValue, T as SitemapIndexEntry, U as SitemapIssue, V as SitemapUrlEntry, W as SitemapValidationResult, X as StatusCode, Y as UaDeviceType, Z as UserAgentInfo, _ as analyzeEmailHeaders, $ as buildCacheControl, a0 as buildDnsQueryUrl, a1 as buildGeoUrl, a2 as buildLinkHeader, a3 as buildMapUrl, a4 as buildRangeHeader, a5 as buildReferrerPolicy, a6 as checkSetCookieHeader, a7 as countryCodeToFlag, a8 as formatCoordinates, a9 as formatTtl, aa as getByCategory, ab as getHeader, ac as getHeadersByCategory, ad as getStatusByCategory, ae as getStatusCode, af as isClientError, ag as isServerError, ah as isSuccess, ai as isValidIp, aj as isValidIpv4, ak as isValidIpv6, al as parseContentRangeHeader, am as parseDnsResponse, an as parseGeoResponse, ao as parseHar, ap as parseIpv6Address, aq as parseUserAgent, ar as searchHeaders, as as searchStatusCodes, at as statusCodeToText, au as typeNumberToLabel, av as validateDomain, aw as validateHeaderName, ax as validateHeaderValue, ay as validateRobotsTxt, az as validateSitemap } from '../network-BC8McQOh.cjs';
1
+ export { A as AuthResultEntry, B as BuildRangeHeaderOptions, C as CacheControlDirective, a as CacheControlOptions, b as CacheControlResult, c as ContentRangeResult, d as CookieAttributes, e as CookieCheckResult, D as DNS_RECORD_TYPES, f as DnsRecord, g as DnsRecordType, h as DnsResponse, E as EmailHeaderAnalysis, i as EmailHeaderField, G as GeoResult, H as HTTP_HEADERS, j as HarEntry, k as HarParseResult, l as HarSummary, m as HeaderCategory, o as HttpHeader, I as Ipv6AddressType, p as Ipv6ParseResult, L as LINK_REL_VALUES, q as LinkHeaderEntry, r as LinkHeaderEntryInput, s as LinkHeaderResult, t as LinkRel, M as ManifestIconInfo, u as ManifestIssue, v as ManifestValidationResult, P as ParsedDnsResult, w as ParsedGeoResult, R as REFERRER_POLICY_VALUES, x as RangeEntry, y as RangeEntryInput, z as RangeHeaderResult, F as ReceivedHop, J as ReferrerPolicyEntry, K as ReferrerPolicyResult, N as ReferrerPolicyValue, O as RobotsGroup, Q as RobotsIssue, S as RobotsRule, T as RobotsValidationResult, U as STATUS_CODES, V as SameSiteValue, W as SitemapIndexEntry, X as SitemapIssue, Y as SitemapUrlEntry, Z as SitemapValidationResult, _ as StatusCode, $ as UaDeviceType, a0 as UserAgentInfo, a1 as VaryHeaderEntry, a2 as VaryHeaderResult, a3 as analyzeEmailHeaders, a4 as buildCacheControl, a5 as buildDnsQueryUrl, a6 as buildGeoUrl, a7 as buildLinkHeader, a8 as buildMapUrl, a9 as buildRangeHeader, aa as buildReferrerPolicy, ab as buildVaryHeader, ac as checkSetCookieHeader, ad as countryCodeToFlag, ae as formatCoordinates, af as formatTtl, ag as getByCategory, ah as getHeader, ai as getHeadersByCategory, aj as getStatusByCategory, ak as getStatusCode, al as isClientError, am as isServerError, an as isSuccess, ao as isValidIp, ap as isValidIpv4, aq as isValidIpv6, ar as parseContentRangeHeader, as as parseDnsResponse, at as parseGeoResponse, au as parseHar, av as parseIpv6Address, aw as parseUserAgent, ax as parseVaryHeader, ay as searchHeaders, az as searchStatusCodes, aA as statusCodeToText, aB as typeNumberToLabel, aC as validateDomain, aD as validateHeaderName, aE as validateHeaderValue, aF as validateManifest, aG as validateRobotsTxt, aH as validateSitemap } from '../network-DISiPMoK.cjs';
@@ -1 +1 @@
1
- export { A as AuthResultEntry, B as BuildRangeHeaderOptions, C as CacheControlDirective, a as CacheControlOptions, b as CacheControlResult, c as ContentRangeResult, d as CookieAttributes, e as CookieCheckResult, D as DNS_RECORD_TYPES, f as DnsRecord, g as DnsRecordType, h as DnsResponse, E as EmailHeaderAnalysis, i as EmailHeaderField, G as GeoResult, H as HTTP_HEADERS, j as HarEntry, k as HarParseResult, l as HarSummary, m as HeaderCategory, o as HttpHeader, I as Ipv6AddressType, p as Ipv6ParseResult, L as LINK_REL_VALUES, q as LinkHeaderEntry, r as LinkHeaderEntryInput, s as LinkHeaderResult, t as LinkRel, P as ParsedDnsResult, u as ParsedGeoResult, R as REFERRER_POLICY_VALUES, v as RangeEntry, w as RangeEntryInput, x as RangeHeaderResult, y as ReceivedHop, z as ReferrerPolicyEntry, F as ReferrerPolicyResult, J as ReferrerPolicyValue, K as RobotsGroup, M as RobotsIssue, N as RobotsRule, O as RobotsValidationResult, S as STATUS_CODES, Q as SameSiteValue, T as SitemapIndexEntry, U as SitemapIssue, V as SitemapUrlEntry, W as SitemapValidationResult, X as StatusCode, Y as UaDeviceType, Z as UserAgentInfo, _ as analyzeEmailHeaders, $ as buildCacheControl, a0 as buildDnsQueryUrl, a1 as buildGeoUrl, a2 as buildLinkHeader, a3 as buildMapUrl, a4 as buildRangeHeader, a5 as buildReferrerPolicy, a6 as checkSetCookieHeader, a7 as countryCodeToFlag, a8 as formatCoordinates, a9 as formatTtl, aa as getByCategory, ab as getHeader, ac as getHeadersByCategory, ad as getStatusByCategory, ae as getStatusCode, af as isClientError, ag as isServerError, ah as isSuccess, ai as isValidIp, aj as isValidIpv4, ak as isValidIpv6, al as parseContentRangeHeader, am as parseDnsResponse, an as parseGeoResponse, ao as parseHar, ap as parseIpv6Address, aq as parseUserAgent, ar as searchHeaders, as as searchStatusCodes, at as statusCodeToText, au as typeNumberToLabel, av as validateDomain, aw as validateHeaderName, ax as validateHeaderValue, ay as validateRobotsTxt, az as validateSitemap } from '../network-BC8McQOh.js';
1
+ export { A as AuthResultEntry, B as BuildRangeHeaderOptions, C as CacheControlDirective, a as CacheControlOptions, b as CacheControlResult, c as ContentRangeResult, d as CookieAttributes, e as CookieCheckResult, D as DNS_RECORD_TYPES, f as DnsRecord, g as DnsRecordType, h as DnsResponse, E as EmailHeaderAnalysis, i as EmailHeaderField, G as GeoResult, H as HTTP_HEADERS, j as HarEntry, k as HarParseResult, l as HarSummary, m as HeaderCategory, o as HttpHeader, I as Ipv6AddressType, p as Ipv6ParseResult, L as LINK_REL_VALUES, q as LinkHeaderEntry, r as LinkHeaderEntryInput, s as LinkHeaderResult, t as LinkRel, M as ManifestIconInfo, u as ManifestIssue, v as ManifestValidationResult, P as ParsedDnsResult, w as ParsedGeoResult, R as REFERRER_POLICY_VALUES, x as RangeEntry, y as RangeEntryInput, z as RangeHeaderResult, F as ReceivedHop, J as ReferrerPolicyEntry, K as ReferrerPolicyResult, N as ReferrerPolicyValue, O as RobotsGroup, Q as RobotsIssue, S as RobotsRule, T as RobotsValidationResult, U as STATUS_CODES, V as SameSiteValue, W as SitemapIndexEntry, X as SitemapIssue, Y as SitemapUrlEntry, Z as SitemapValidationResult, _ as StatusCode, $ as UaDeviceType, a0 as UserAgentInfo, a1 as VaryHeaderEntry, a2 as VaryHeaderResult, a3 as analyzeEmailHeaders, a4 as buildCacheControl, a5 as buildDnsQueryUrl, a6 as buildGeoUrl, a7 as buildLinkHeader, a8 as buildMapUrl, a9 as buildRangeHeader, aa as buildReferrerPolicy, ab as buildVaryHeader, ac as checkSetCookieHeader, ad as countryCodeToFlag, ae as formatCoordinates, af as formatTtl, ag as getByCategory, ah as getHeader, ai as getHeadersByCategory, aj as getStatusByCategory, ak as getStatusCode, al as isClientError, am as isServerError, an as isSuccess, ao as isValidIp, ap as isValidIpv4, aq as isValidIpv6, ar as parseContentRangeHeader, as as parseDnsResponse, at as parseGeoResponse, au as parseHar, av as parseIpv6Address, aw as parseUserAgent, ax as parseVaryHeader, ay as searchHeaders, az as searchStatusCodes, aA as statusCodeToText, aB as typeNumberToLabel, aC as validateDomain, aD as validateHeaderName, aE as validateHeaderValue, aF as validateManifest, aG as validateRobotsTxt, aH as validateSitemap } from '../network-DISiPMoK.js';
@@ -1,2 +1,2 @@
1
- export { DNS_RECORD_TYPES, HTTP_HEADERS, LINK_REL_VALUES, REFERRER_POLICY_VALUES, STATUS_CODES, analyzeEmailHeaders, buildCacheControl, buildDnsQueryUrl, buildGeoUrl, buildLinkHeader, buildMapUrl, buildRangeHeader, buildReferrerPolicy, checkSetCookieHeader, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, parseContentRangeHeader, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parseUserAgent, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateRobotsTxt, validateSitemap } from '../chunk-7WSFJTYP.js';
1
+ export { DNS_RECORD_TYPES, HTTP_HEADERS, LINK_REL_VALUES, REFERRER_POLICY_VALUES, STATUS_CODES, analyzeEmailHeaders, buildCacheControl, buildDnsQueryUrl, buildGeoUrl, buildLinkHeader, buildMapUrl, buildRangeHeader, buildReferrerPolicy, buildVaryHeader, checkSetCookieHeader, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, parseContentRangeHeader, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parseUserAgent, parseVaryHeader, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateManifest, validateRobotsTxt, validateSitemap } from '../chunk-XPNZYPM5.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.41.0",
3
+ "version": "0.43.0",
4
4
  "description": "154+ 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",