run402-mcp
Version:
MCP server for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.
140 lines • 4.31 kB
JavaScript
import { LocalError } from "./errors.js";
const KNOWN_BINARY_EXTENSIONS = new Set([
"7z",
"avif",
"bin",
"bmp",
"br",
"dds",
"eot",
"flac",
"gif",
"gz",
"heic",
"heif",
"ico",
"jpeg",
"jpg",
"ktx",
"ktx2",
"m4a",
"m4v",
"mov",
"mp3",
"mp4",
"ogg",
"ogv",
"opus",
"otf",
"pak",
"pdf",
"png",
"rar",
"tar",
"tif",
"tiff",
"ttf",
"wasm",
"wav",
"webm",
"webp",
"woff",
"woff2",
"zip",
]);
const KNOWN_BINARY_APPLICATION_TYPES = new Set([
"application/gzip",
"application/octet-stream",
"application/pdf",
"application/vnd.ms-fontobject",
"application/wasm",
"application/x-7z-compressed",
"application/x-rar-compressed",
"application/zip",
"model/gltf-binary",
]);
/**
* True when a path/content-type pair describes bytes that must not originate
* from a JavaScript string. This is deliberately conservative: textual image
* formats such as SVG stay valid string sources, while opaque octet streams
* are rejected only for extensions that are known to be binary.
*/
export function isKnownBinaryContent(path, contentType) {
const mediaType = contentType.split(";", 1)[0].trim().toLowerCase();
const basename = path.split(/[\\/]/).pop() ?? path;
const dot = basename.lastIndexOf(".");
const extension = dot >= 0 ? basename.slice(dot + 1).toLowerCase() : "";
if (mediaType.startsWith("audio/") || mediaType.startsWith("video/") || mediaType.startsWith("font/")) {
return true;
}
if (mediaType.startsWith("image/") && mediaType !== "image/svg+xml") {
return true;
}
if (mediaType === "application/octet-stream") {
return KNOWN_BINARY_EXTENSIONS.has(extension);
}
return KNOWN_BINARY_APPLICATION_TYPES.has(mediaType) || KNOWN_BINARY_EXTENSIONS.has(extension);
}
/** True for a direct string or a `{ data: ... }` wrapper around one. */
export function isUtf8StringSource(source) {
if (typeof source === "string")
return true;
if (source !== null &&
typeof source === "object" &&
!Array.isArray(source) &&
"data" in source) {
return isUtf8StringSource(source.data);
}
return false;
}
export function assertPositiveSafeInteger(value, name, context) {
if (!Number.isSafeInteger(value) || value <= 0) {
throw new LocalError(`${name} must be a positive safe integer.`, context);
}
}
export function assertWeiString(value, name, context) {
if (typeof value !== "string" || !/^\d+$/.test(value)) {
throw new LocalError(`${name} must be a decimal non-negative integer string in wei.`, context);
}
}
export function assertEvmAddress(value, name, context) {
if (typeof value !== "string" || !/^0x[a-fA-F0-9]{40}$/.test(value)) {
throw new LocalError(`${name} must be a 0x-prefixed 20-byte EVM address.`, context);
}
}
export function assertNonEmptyString(value, name, context) {
if (typeof value !== "string" || value.length === 0) {
throw new LocalError(`${name} must be a non-empty string.`, context);
}
}
export function assertEmailAddress(value, name, context) {
if (typeof value !== "string" ||
value.length > 320 ||
!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
throw new LocalError(`${name} must be a valid email address.`, context);
}
}
export function assertHttpUrl(value, name, context) {
if (typeof value !== "string" || value.length === 0) {
throw new LocalError(`${name} must be an http(s) URL.`, context);
}
let url;
try {
url = new URL(value);
}
catch {
throw new LocalError(`${name} must be an http(s) URL.`, context);
}
if (url.protocol !== "http:" && url.protocol !== "https:") {
throw new LocalError(`${name} must be an http(s) URL.`, context);
}
}
export function assertStringInSet(value, allowed, name, context) {
if (typeof value !== "string") {
throw new LocalError(`${name} must be one of: ${allowed.join(", ")}.`, context);
}
if (!allowed.includes(value)) {
throw new LocalError(`${name} must be one of: ${allowed.join(", ")}.`, context);
}
}
//# sourceMappingURL=validation.js.map