From 6bf57766feb8321f860baf300140563cd9539053 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Sun, 14 Dec 2025 20:36:24 -0800 Subject: Init --- src/types/index.ts | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/types/index.ts (limited to 'src/types') diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..fbfc70d --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,78 @@ +export enum ContentType { + JSON = 'json', + FORM = 'form', + MULTIPART = 'multipart', + TEXT = 'text', + RAW = 'raw', +} + +export interface NtfyConfig { + enabled: boolean; + server?: string; + topic?: string; +} + +export interface RouteConfig { + name: string; + contentType: ContentType; + hcaptchaProtected: boolean; + hcaptchaSecret?: string; + ntfy?: NtfyConfig; + requireToken?: boolean; +} + +export interface StoredRequest { + timestamp: number; + uuid: string; + routeName: string; + method: string; + headers: Record; + body: unknown; + files?: Array<{ + filename: string; + contentType: string; + size: number; + path: string; + }>; +} + +const ROUTE_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]{0,63}$/i; + +export function isSafeRouteName(name: unknown): name is string { + if (typeof name !== 'string') return false; + if (name !== name.trim()) return false; + if (name === '.' || name === '..') return false; + if (name.includes('/') || name.includes('\\')) return false; + return ROUTE_NAME_PATTERN.test(name); +} + +export function isRouteConfig(obj: unknown): obj is RouteConfig { + if (typeof obj !== 'object' || obj === null) return false; + const r = obj as Record; + + const validBasic = + isSafeRouteName(r.name) && + typeof r.contentType === 'string' && + Object.values(ContentType).includes(r.contentType as ContentType) && + typeof r.hcaptchaProtected === 'boolean' && + (r.hcaptchaProtected === false || typeof r.hcaptchaSecret === 'string'); + + if (!validBasic) return false; + + // Validate ntfy config if present + if (r.ntfy !== undefined) { + if (typeof r.ntfy !== 'object' || r.ntfy === null) return false; + const ntfy = r.ntfy as Record; + if (typeof ntfy.enabled !== 'boolean') return false; + if (ntfy.enabled && (typeof ntfy.server !== 'string' || typeof ntfy.topic !== 'string')) { + return false; + } + } + + // Validate requireToken if present + if (r.requireToken !== undefined && typeof r.requireToken !== 'boolean') { + return false; + } + + return true; +} -- cgit v1.2.3-70-g09d2