@doclo/core 0.1.5

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/runtime/crypto.ts"],"sourcesContent":["/**\n * Universal Crypto Adapter\n *\n * Provides crypto-secure random byte generation for both Node.js and Edge Runtime.\n * Uses Web Crypto API (available in both environments) for maximum compatibility.\n *\n * @module @doclo/core/runtime/crypto\n */\n\n/**\n * Generate crypto-secure random bytes\n *\n * Uses Web Crypto API which is available in:\n * - Node.js 18+ (globalThis.crypto)\n * - Browsers (window.crypto)\n * - Cloudflare Workers (crypto)\n * - Vercel Edge Functions (crypto)\n *\n * @param length - Number of random bytes to generate\n * @returns Uint8Array containing random bytes\n */\nexport function getRandomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n\n // Use Web Crypto API (available in all supported runtimes)\n // Node.js 18+, Edge Runtime, and browsers all support globalThis.crypto\n if (typeof globalThis !== 'undefined' && globalThis.crypto?.getRandomValues) {\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n }\n\n throw new Error(\n 'Web Crypto API not available. This SDK requires:\\n' +\n '- Node.js 18.0.0 or later (has globalThis.crypto)\\n' +\n '- Edge Runtime (Vercel, Cloudflare)\\n' +\n '- Modern browsers'\n );\n}\n\n/**\n * Convert Uint8Array to lowercase hex string\n *\n * @param bytes - Byte array to convert\n * @returns Hex string representation\n */\nexport function bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Generate random hex string of specified byte length\n *\n * @param byteLength - Number of random bytes (hex string will be 2x this length)\n * @returns Lowercase hex string\n *\n * @example\n * ```typescript\n * const traceId = randomHex(16); // 32 hex characters\n * const spanId = randomHex(8); // 16 hex characters\n * ```\n */\nexport function randomHex(byteLength: number): string {\n const bytes = getRandomBytes(byteLength);\n return bytesToHex(bytes);\n}\n\n/**\n * Generate a UUID v4 string\n *\n * Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\n *\n * @returns UUID v4 string\n *\n * @example\n * ```typescript\n * const id = randomUUID(); // \"550e8400-e29b-41d4-a716-446655440000\"\n * ```\n */\nexport function randomUUID(): string {\n // Try native crypto.randomUUID() first (Node 19+, all Edge runtimes)\n if (typeof globalThis !== 'undefined' && globalThis.crypto?.randomUUID) {\n return globalThis.crypto.randomUUID();\n }\n\n // Fallback: Manual UUID v4 generation\n const bytes = getRandomBytes(16);\n\n // Set version (4) and variant bits for UUID v4\n bytes[6] = (bytes[6] & 0x0f) | 0x40; // Version 4\n bytes[8] = (bytes[8] & 0x3f) | 0x80; // Variant 10\n\n // Format as UUID string\n const hex = bytesToHex(bytes);\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;\n}\n"],"mappings":";AAqBO,SAAS,eAAe,QAA4B;AACzD,QAAM,QAAQ,IAAI,WAAW,MAAM;AAInC,MAAI,OAAO,eAAe,eAAe,WAAW,QAAQ,iBAAiB;AAC3E,eAAW,OAAO,gBAAgB,KAAK;AACvC,WAAO;AAAA,EACT;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EAIF;AACF;AAQO,SAAS,WAAW,OAA2B;AACpD,SAAO,MAAM,KAAK,KAAK,EACpB,IAAI,OAAK,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EACxC,KAAK,EAAE;AACZ;AAcO,SAAS,UAAU,YAA4B;AACpD,QAAM,QAAQ,eAAe,UAAU;AACvC,SAAO,WAAW,KAAK;AACzB;AAcO,SAAS,aAAqB;AAEnC,MAAI,OAAO,eAAe,eAAe,WAAW,QAAQ,YAAY;AACtE,WAAO,WAAW,OAAO,WAAW;AAAA,EACtC;AAGA,QAAM,QAAQ,eAAe,EAAE;AAG/B,QAAM,CAAC,IAAK,MAAM,CAAC,IAAI,KAAQ;AAC/B,QAAM,CAAC,IAAK,MAAM,CAAC,IAAI,KAAQ;AAG/B,QAAM,MAAM,WAAW,KAAK;AAC5B,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC;AAC9G;","names":[]}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Universal Environment Configuration
3
+ *
4
+ * Provides environment variable access for both Node.js and Edge Runtime.
5
+ * Supports multiple patterns:
6
+ * - Node.js: process.env
7
+ * - Vercel Edge Functions: process.env (available)
8
+ * - Cloudflare Workers: env bindings (passed as config)
9
+ *
10
+ * @module @doclo/core/runtime/env
11
+ */
12
+ /**
13
+ * Runtime environment configuration
14
+ *
15
+ * Can be set explicitly or will fall back to process.env when available.
16
+ */
17
+ interface RuntimeEnv {
18
+ /**
19
+ * Node environment (development, production, test)
20
+ */
21
+ NODE_ENV?: string;
22
+ /**
23
+ * Debug flag for validation messages
24
+ */
25
+ DEBUG_VALIDATION?: string;
26
+ /**
27
+ * Skip flow validation (use with caution!)
28
+ */
29
+ DOCLO_SKIP_VALIDATION?: string;
30
+ /**
31
+ * Endpoint for security event logging
32
+ */
33
+ SECURITY_LOG_ENDPOINT?: string;
34
+ /**
35
+ * Additional environment variables
36
+ */
37
+ [key: string]: string | undefined;
38
+ }
39
+ /**
40
+ * Set global runtime environment configuration
41
+ *
42
+ * Use this to configure environment variables in Edge Runtime environments
43
+ * where process.env is not available (like Cloudflare Workers).
44
+ *
45
+ * @param env - Environment configuration object
46
+ */
47
+ declare function setRuntimeEnv(env: RuntimeEnv): void;
48
+ /**
49
+ * Get global runtime environment configuration
50
+ *
51
+ * @returns Current runtime environment config or null
52
+ */
53
+ declare function getRuntimeEnv(): RuntimeEnv | null;
54
+ /**
55
+ * Clear global runtime environment configuration (for testing)
56
+ */
57
+ declare function clearRuntimeEnv(): void;
58
+ /**
59
+ * Get environment variable value
60
+ *
61
+ * Priority:
62
+ * 1. Explicitly set runtime env (via setRuntimeEnv)
63
+ * 2. process.env (Node.js, Vercel Edge)
64
+ * 3. undefined
65
+ *
66
+ * @param key - Environment variable name
67
+ * @param defaultValue - Optional default value if not found
68
+ * @returns Environment variable value or undefined
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * const nodeEnv = getEnv('NODE_ENV', 'development');
73
+ * const isProduction = nodeEnv === 'production';
74
+ *
75
+ * const skipValidation = getEnv('DOCLO_SKIP_VALIDATION') === 'true';
76
+ * ```
77
+ */
78
+ declare function getEnv(key: string, defaultValue?: string): string | undefined;
79
+ /**
80
+ * Check if running in production mode
81
+ *
82
+ * @returns True if NODE_ENV is 'production'
83
+ */
84
+ declare function isProduction(): boolean;
85
+ /**
86
+ * Check if running in development mode
87
+ *
88
+ * @returns True if NODE_ENV is 'development'
89
+ */
90
+ declare function isDevelopment(): boolean;
91
+ /**
92
+ * Check if running in test mode
93
+ *
94
+ * @returns True if NODE_ENV is 'test'
95
+ */
96
+ declare function isTest(): boolean;
97
+ /**
98
+ * Check if debug validation is enabled
99
+ *
100
+ * @returns True if DEBUG_VALIDATION is set to any truthy value
101
+ */
102
+ declare function isDebugValidation(): boolean;
103
+ /**
104
+ * Check if validation should be skipped
105
+ *
106
+ * CAUTION: Only use in trusted environments!
107
+ *
108
+ * @returns True if DOCLO_SKIP_VALIDATION is 'true'
109
+ */
110
+ declare function shouldSkipValidation(): boolean;
111
+ /**
112
+ * Detect current runtime environment
113
+ *
114
+ * @returns Runtime type: 'node', 'edge-vercel', 'workerd' (Cloudflare), 'browser', or 'unknown'
115
+ */
116
+ declare function detectRuntime(): 'node' | 'edge-vercel' | 'workerd' | 'browser' | 'unknown';
117
+ /**
118
+ * Check if running in an Edge Runtime environment
119
+ *
120
+ * @returns True if running in Vercel Edge or Cloudflare Workers
121
+ */
122
+ declare function isEdgeRuntime(): boolean;
123
+ /**
124
+ * Check if running in Node.js
125
+ *
126
+ * @returns True if running in Node.js
127
+ */
128
+ declare function isNodeRuntime(): boolean;
129
+
130
+ export { type RuntimeEnv, clearRuntimeEnv, detectRuntime, getEnv, getRuntimeEnv, isDebugValidation, isDevelopment, isEdgeRuntime, isNodeRuntime, isProduction, isTest, setRuntimeEnv, shouldSkipValidation };
@@ -0,0 +1,76 @@
1
+ // src/runtime/env.ts
2
+ var globalRuntimeEnv = null;
3
+ function setRuntimeEnv(env) {
4
+ globalRuntimeEnv = env;
5
+ }
6
+ function getRuntimeEnv() {
7
+ return globalRuntimeEnv;
8
+ }
9
+ function clearRuntimeEnv() {
10
+ globalRuntimeEnv = null;
11
+ }
12
+ function getEnv(key, defaultValue) {
13
+ if (globalRuntimeEnv && key in globalRuntimeEnv) {
14
+ return globalRuntimeEnv[key];
15
+ }
16
+ if (typeof process !== "undefined" && process.env) {
17
+ const value = process.env[key];
18
+ if (value !== void 0) {
19
+ return value;
20
+ }
21
+ }
22
+ return defaultValue;
23
+ }
24
+ function isProduction() {
25
+ return getEnv("NODE_ENV") === "production";
26
+ }
27
+ function isDevelopment() {
28
+ return getEnv("NODE_ENV") === "development";
29
+ }
30
+ function isTest() {
31
+ return getEnv("NODE_ENV") === "test";
32
+ }
33
+ function isDebugValidation() {
34
+ const debug = getEnv("DEBUG_VALIDATION");
35
+ return Boolean(debug && debug !== "0" && debug !== "false");
36
+ }
37
+ function shouldSkipValidation() {
38
+ return getEnv("DOCLO_SKIP_VALIDATION") === "true";
39
+ }
40
+ function detectRuntime() {
41
+ if (typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers") {
42
+ return "workerd";
43
+ }
44
+ if (typeof globalThis !== "undefined" && "EdgeRuntime" in globalThis) {
45
+ return "edge-vercel";
46
+ }
47
+ if (typeof process !== "undefined" && process.versions?.node) {
48
+ return "node";
49
+ }
50
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
51
+ return "browser";
52
+ }
53
+ return "unknown";
54
+ }
55
+ function isEdgeRuntime() {
56
+ const runtime = detectRuntime();
57
+ return runtime === "edge-vercel" || runtime === "workerd";
58
+ }
59
+ function isNodeRuntime() {
60
+ return detectRuntime() === "node";
61
+ }
62
+ export {
63
+ clearRuntimeEnv,
64
+ detectRuntime,
65
+ getEnv,
66
+ getRuntimeEnv,
67
+ isDebugValidation,
68
+ isDevelopment,
69
+ isEdgeRuntime,
70
+ isNodeRuntime,
71
+ isProduction,
72
+ isTest,
73
+ setRuntimeEnv,
74
+ shouldSkipValidation
75
+ };
76
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/runtime/env.ts"],"sourcesContent":["/**\n * Universal Environment Configuration\n *\n * Provides environment variable access for both Node.js and Edge Runtime.\n * Supports multiple patterns:\n * - Node.js: process.env\n * - Vercel Edge Functions: process.env (available)\n * - Cloudflare Workers: env bindings (passed as config)\n *\n * @module @doclo/core/runtime/env\n */\n\n/**\n * Runtime environment configuration\n *\n * Can be set explicitly or will fall back to process.env when available.\n */\nexport interface RuntimeEnv {\n /**\n * Node environment (development, production, test)\n */\n NODE_ENV?: string;\n\n /**\n * Debug flag for validation messages\n */\n DEBUG_VALIDATION?: string;\n\n /**\n * Skip flow validation (use with caution!)\n */\n DOCLO_SKIP_VALIDATION?: string;\n\n /**\n * Endpoint for security event logging\n */\n SECURITY_LOG_ENDPOINT?: string;\n\n /**\n * Additional environment variables\n */\n [key: string]: string | undefined;\n}\n\n/**\n * Global runtime environment configuration\n *\n * Set this at application startup to configure environment for Edge Runtime.\n * Falls back to process.env when not set.\n *\n * @example\n * ```typescript\n * // Cloudflare Workers\n * export default {\n * async fetch(request: Request, env: Env) {\n * setRuntimeEnv(env);\n * // ... use SDK\n * }\n * }\n *\n * // Vercel Edge Functions (process.env works, but can override)\n * setRuntimeEnv({ NODE_ENV: 'production' });\n * ```\n */\nlet globalRuntimeEnv: RuntimeEnv | null = null;\n\n/**\n * Set global runtime environment configuration\n *\n * Use this to configure environment variables in Edge Runtime environments\n * where process.env is not available (like Cloudflare Workers).\n *\n * @param env - Environment configuration object\n */\nexport function setRuntimeEnv(env: RuntimeEnv): void {\n globalRuntimeEnv = env;\n}\n\n/**\n * Get global runtime environment configuration\n *\n * @returns Current runtime environment config or null\n */\nexport function getRuntimeEnv(): RuntimeEnv | null {\n return globalRuntimeEnv;\n}\n\n/**\n * Clear global runtime environment configuration (for testing)\n */\nexport function clearRuntimeEnv(): void {\n globalRuntimeEnv = null;\n}\n\n/**\n * Get environment variable value\n *\n * Priority:\n * 1. Explicitly set runtime env (via setRuntimeEnv)\n * 2. process.env (Node.js, Vercel Edge)\n * 3. undefined\n *\n * @param key - Environment variable name\n * @param defaultValue - Optional default value if not found\n * @returns Environment variable value or undefined\n *\n * @example\n * ```typescript\n * const nodeEnv = getEnv('NODE_ENV', 'development');\n * const isProduction = nodeEnv === 'production';\n *\n * const skipValidation = getEnv('DOCLO_SKIP_VALIDATION') === 'true';\n * ```\n */\nexport function getEnv(key: string, defaultValue?: string): string | undefined {\n // 1. Check explicitly set runtime env\n if (globalRuntimeEnv && key in globalRuntimeEnv) {\n return globalRuntimeEnv[key];\n }\n\n // 2. Check process.env (Node.js, Vercel Edge)\n if (typeof process !== 'undefined' && process.env) {\n const value = process.env[key];\n if (value !== undefined) {\n return value;\n }\n }\n\n // 3. Return default value\n return defaultValue;\n}\n\n/**\n * Check if running in production mode\n *\n * @returns True if NODE_ENV is 'production'\n */\nexport function isProduction(): boolean {\n return getEnv('NODE_ENV') === 'production';\n}\n\n/**\n * Check if running in development mode\n *\n * @returns True if NODE_ENV is 'development'\n */\nexport function isDevelopment(): boolean {\n return getEnv('NODE_ENV') === 'development';\n}\n\n/**\n * Check if running in test mode\n *\n * @returns True if NODE_ENV is 'test'\n */\nexport function isTest(): boolean {\n return getEnv('NODE_ENV') === 'test';\n}\n\n/**\n * Check if debug validation is enabled\n *\n * @returns True if DEBUG_VALIDATION is set to any truthy value\n */\nexport function isDebugValidation(): boolean {\n const debug = getEnv('DEBUG_VALIDATION');\n return Boolean(debug && debug !== '0' && debug !== 'false');\n}\n\n/**\n * Check if validation should be skipped\n *\n * CAUTION: Only use in trusted environments!\n *\n * @returns True if DOCLO_SKIP_VALIDATION is 'true'\n */\nexport function shouldSkipValidation(): boolean {\n return getEnv('DOCLO_SKIP_VALIDATION') === 'true';\n}\n\n/**\n * Detect current runtime environment\n *\n * @returns Runtime type: 'node', 'edge-vercel', 'workerd' (Cloudflare), 'browser', or 'unknown'\n */\nexport function detectRuntime(): 'node' | 'edge-vercel' | 'workerd' | 'browser' | 'unknown' {\n // Check for Cloudflare Workers\n if (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') {\n return 'workerd';\n }\n\n // Check for Vercel Edge Functions\n if (typeof globalThis !== 'undefined' && 'EdgeRuntime' in globalThis) {\n return 'edge-vercel';\n }\n\n // Check for Node.js\n if (typeof process !== 'undefined' && process.versions?.node) {\n return 'node';\n }\n\n // Check for browser\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n return 'browser';\n }\n\n return 'unknown';\n}\n\n/**\n * Check if running in an Edge Runtime environment\n *\n * @returns True if running in Vercel Edge or Cloudflare Workers\n */\nexport function isEdgeRuntime(): boolean {\n const runtime = detectRuntime();\n return runtime === 'edge-vercel' || runtime === 'workerd';\n}\n\n/**\n * Check if running in Node.js\n *\n * @returns True if running in Node.js\n */\nexport function isNodeRuntime(): boolean {\n return detectRuntime() === 'node';\n}\n"],"mappings":";AAgEA,IAAI,mBAAsC;AAUnC,SAAS,cAAc,KAAuB;AACnD,qBAAmB;AACrB;AAOO,SAAS,gBAAmC;AACjD,SAAO;AACT;AAKO,SAAS,kBAAwB;AACtC,qBAAmB;AACrB;AAsBO,SAAS,OAAO,KAAa,cAA2C;AAE7E,MAAI,oBAAoB,OAAO,kBAAkB;AAC/C,WAAO,iBAAiB,GAAG;AAAA,EAC7B;AAGA,MAAI,OAAO,YAAY,eAAe,QAAQ,KAAK;AACjD,UAAM,QAAQ,QAAQ,IAAI,GAAG;AAC7B,QAAI,UAAU,QAAW;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAGA,SAAO;AACT;AAOO,SAAS,eAAwB;AACtC,SAAO,OAAO,UAAU,MAAM;AAChC;AAOO,SAAS,gBAAyB;AACvC,SAAO,OAAO,UAAU,MAAM;AAChC;AAOO,SAAS,SAAkB;AAChC,SAAO,OAAO,UAAU,MAAM;AAChC;AAOO,SAAS,oBAA6B;AAC3C,QAAM,QAAQ,OAAO,kBAAkB;AACvC,SAAO,QAAQ,SAAS,UAAU,OAAO,UAAU,OAAO;AAC5D;AASO,SAAS,uBAAgC;AAC9C,SAAO,OAAO,uBAAuB,MAAM;AAC7C;AAOO,SAAS,gBAA4E;AAE1F,MAAI,OAAO,cAAc,eAAe,UAAU,cAAc,sBAAsB;AACpF,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,eAAe,eAAe,iBAAiB,YAAY;AACpE,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,YAAY,eAAe,QAAQ,UAAU,MAAM;AAC5D,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AACpE,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAOO,SAAS,gBAAyB;AACvC,QAAM,UAAU,cAAc;AAC9B,SAAO,YAAY,iBAAiB,YAAY;AAClD;AAOO,SAAS,gBAAyB;AACvC,SAAO,cAAc,MAAM;AAC7B;","names":[]}
@@ -0,0 +1,236 @@
1
+ /**
2
+ * URL Validation and SSRF Protection
3
+ *
4
+ * ⚠️ SECURITY CRITICAL: SSRF (Server-Side Request Forgery) Prevention
5
+ *
6
+ * This module blocks URLs that could be used in Server-Side Request Forgery attacks:
7
+ * - Internal IP addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
8
+ * - Loopback addresses (127.0.0.0/8, ::1)
9
+ * - Cloud metadata services (AWS, GCP, Aliyun, etc.)
10
+ * - Link-local addresses (169.254.0.0/16)
11
+ *
12
+ * Attack example: An attacker tricks your server to make requests to:
13
+ * - http://169.254.169.254 (AWS credentials endpoint)
14
+ * - http://10.0.0.1:8080/admin (internal service)
15
+ * - http://localhost/api/admin (localhost admin endpoint)
16
+ *
17
+ * Prevents Server-Side Request Forgery attacks by validating URLs against blocklist
18
+ */
19
+ /**
20
+ * Validate a URL to prevent SSRF (Server-Side Request Forgery) attacks
21
+ *
22
+ * ⚠️ SECURITY CRITICAL: SSRF Prevention
23
+ *
24
+ * This function blocks URLs that could be used to exploit the server:
25
+ * - Internal IP addresses (breaks firewall perimeter security)
26
+ * - Cloud metadata services (leaks credentials, API keys)
27
+ * - Localhost/loopback (access admin services, debug ports)
28
+ *
29
+ * By default, blocks internal network access automatically.
30
+ *
31
+ * @param urlString - The URL to validate
32
+ * @param options - Validation options
33
+ * - blockInternal (default: true) - Block internal IP ranges. ⚠️ Set to false only if you understand SSRF risks
34
+ * - allowedProtocols (default: ['http:', 'https:']) - Restrict to specific protocols
35
+ * @throws Error if URL is invalid, uses blocked protocol, or points to blocked IP/host
36
+ * @returns The validated URL object
37
+ * @security Always validate user-provided URLs. Do not set blockInternal to false without SSRF security review
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // Validate user-provided URL
42
+ * try {
43
+ * const url = validateUrl(userInput);
44
+ * const response = await fetch(url.toString());
45
+ * } catch (error) {
46
+ * // URL was malicious or pointed to internal resource
47
+ * }
48
+ * ```
49
+ */
50
+ declare function validateUrl(urlString: string, options?: {
51
+ blockInternal?: boolean;
52
+ allowedProtocols?: string[];
53
+ }): URL;
54
+ /**
55
+ * Fetch a URL with SSRF protection and timeout
56
+ * @param url - The URL to fetch
57
+ * @param timeoutMs - Request timeout in milliseconds (default 30s)
58
+ * @throws Error if URL is invalid, blocked, or request times out
59
+ */
60
+ declare function secureFetch(url: string, timeoutMs?: number): Promise<Response>;
61
+ /**
62
+ * Extract hostname from URL string for validation
63
+ * Useful for pre-validation checks before full URL parsing
64
+ */
65
+ declare function getHostnameFromUrl(urlString: string): string;
66
+
67
+ /**
68
+ * Path Validation and Path Traversal Prevention
69
+ * Prevents attackers from accessing arbitrary files through path traversal
70
+ */
71
+ /**
72
+ * Validate and normalize a file path to prevent traversal attacks
73
+ * @param filePath - The file path to validate
74
+ * @param basePath - The base directory that paths must be within
75
+ * @throws Error if path attempts to traverse outside basePath
76
+ * @returns The normalized safe path
77
+ */
78
+ declare function validatePath(filePath: string, basePath: string): string;
79
+ /**
80
+ * Validate a path without a required base path (more permissive)
81
+ * Still prevents obvious traversal attempts
82
+ * @param filePath - The file path to validate
83
+ * @throws Error if path contains suspicious traversal patterns
84
+ * @returns The normalized path
85
+ */
86
+ declare function validatePathSimple(filePath: string): string;
87
+ /**
88
+ * Check if a path would be safe to access
89
+ * @param filePath - The file path to check
90
+ * @param basePath - Optional base path restriction
91
+ * @returns true if path is safe, false otherwise
92
+ */
93
+ declare function isPathSafe(filePath: string, basePath?: string): boolean;
94
+ /**
95
+ * Get the absolute path with validation
96
+ * @param filePath - The file path
97
+ * @param basePath - Optional base directory
98
+ * @returns Absolute path if valid
99
+ * @throws Error if path is invalid
100
+ */
101
+ declare function getSafePath(filePath: string, basePath?: string): string;
102
+
103
+ /**
104
+ * Resource Limits and DoS Protection
105
+ *
106
+ * ⚠️ SECURITY WARNING: Resource limits are critical for protecting against:
107
+ * - Resource exhaustion attacks (large file downloads)
108
+ * - Denial of Service (slow loris, timeout attacks)
109
+ * - Memory exhaustion (deeply nested JSON, large arrays)
110
+ *
111
+ * Prevents resource exhaustion attacks through file size limits and timeouts
112
+ */
113
+ /**
114
+ * Default resource limits
115
+ *
116
+ * ⚠️ SECURITY CRITICAL: These are conservative defaults designed to prevent DoS attacks.
117
+ *
118
+ * - MAX_FILE_SIZE (100MB): Prevents downloading very large files that could exhaust memory or disk
119
+ * - REQUEST_TIMEOUT (30s): Prevents slow-loris attacks and hung connections
120
+ * - MAX_JSON_DEPTH (100): Prevents billion laughs attack (deeply nested JSON)
121
+ *
122
+ * Do not increase these limits without understanding the security implications:
123
+ * - Higher file size limit → Greater risk of resource exhaustion
124
+ * - Lower timeout → May reject legitimate slow requests
125
+ * - Lower JSON depth → May reject valid documents
126
+ *
127
+ * @security These limits can be overridden by SDK users, but doing so reduces security.
128
+ */
129
+ declare const DEFAULT_LIMITS: {
130
+ MAX_FILE_SIZE: number;
131
+ REQUEST_TIMEOUT: number;
132
+ MAX_JSON_DEPTH: number;
133
+ };
134
+ /**
135
+ * Validate file size before processing
136
+ *
137
+ * ⚠️ SECURITY WARNING: File size validation prevents resource exhaustion.
138
+ * - Without limits: attackers can force downloads of multi-gigabyte files
139
+ * - Memory impact: files are loaded into memory for base64 encoding
140
+ * - Disk impact: temporary storage of downloaded files
141
+ *
142
+ * @param size - The file size in bytes
143
+ * @param maxSize - Maximum allowed size in bytes (default 100MB, can be customized)
144
+ * @throws Error if file exceeds size limit
145
+ * @security Do not disable this check without understanding resource implications
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * // Standard check with default limit (100MB)
150
+ * validateFileSize(fileSize);
151
+ *
152
+ * // Custom limit for use case that requires larger files
153
+ * validateFileSize(fileSize, 500 * 1024 * 1024); // 500MB
154
+ * ```
155
+ */
156
+ declare function validateFileSize(size: number, maxSize?: number): void;
157
+ /**
158
+ * Create a fetch controller with timeout
159
+ * @param timeoutMs - Timeout in milliseconds (default 30s)
160
+ * @returns AbortController with timeout configured
161
+ */
162
+ declare function createFetchController(timeoutMs?: number): AbortController;
163
+ /**
164
+ * Clean up fetch controller timeout
165
+ * @param controller - The AbortController to clean up
166
+ */
167
+ declare function cleanupFetchController(controller: AbortController): void;
168
+ /**
169
+ * Execute a fetch with automatic timeout and cleanup
170
+ *
171
+ * ⚠️ SECURITY WARNING: Timeout protection prevents slow-loris and other timing attacks.
172
+ * - Without timeout: requests can hang indefinitely, consuming server resources
173
+ * - Slow-loris attack: attacker sends requests slowly to exhaust connection pool
174
+ * - Zombie connections: closed clients but open server connections
175
+ *
176
+ * Default timeout (30s) balances security with legitimate use:
177
+ * - Too short: may reject slow networks or legitimate large downloads
178
+ * - Too long: keeps server resources tied up, enables DoS attacks
179
+ *
180
+ * @param url - The URL to fetch
181
+ * @param options - Fetch options (method, headers, body, etc.)
182
+ * @param timeoutMs - Timeout in milliseconds (default 30s, can be customized)
183
+ * @returns The fetch response
184
+ * @throws Error if request times out
185
+ * @security Do not use very long timeouts without understanding DoS implications
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * // Default timeout (30 seconds)
190
+ * const response = await fetchWithTimeout('https://example.com/file.pdf');
191
+ *
192
+ * // Custom timeout for slower connections
193
+ * const response = await fetchWithTimeout(url, options, 60000); // 60 seconds
194
+ * ```
195
+ */
196
+ declare function fetchWithTimeout(url: string, options?: RequestInit, timeoutMs?: number): Promise<Response>;
197
+ /**
198
+ * Check buffer size before allocation
199
+ * @param size - The buffer size in bytes
200
+ * @param maxSize - Maximum allowed size (default 100MB)
201
+ * @throws Error if buffer would exceed memory limit
202
+ */
203
+ declare function validateBufferSize(size: number, maxSize?: number): void;
204
+ /**
205
+ * Memory-safe JSON parse with depth limit
206
+ *
207
+ * ⚠️ SECURITY WARNING: Depth limits prevent billion laughs / XML bomb attacks in JSON format.
208
+ * - Billion laughs attack: deeply nested JSON causes exponential memory expansion
209
+ * - Stack overflow: deeply nested structures can exhaust call stack
210
+ * - Resource exhaustion: parsing deeply nested JSON consumes CPU and memory
211
+ *
212
+ * Attack example (evil.json):
213
+ * ```json
214
+ * {"a":{"b":{"c":{"d":{"e":...}}}}} // 1000+ levels deep
215
+ * ```
216
+ *
217
+ * Default limit (100 levels) prevents attacks while allowing legitimate documents.
218
+ *
219
+ * @param text - JSON string to parse
220
+ * @param maxDepth - Maximum nesting depth in levels (default 100, can be customized)
221
+ * @returns Parsed object
222
+ * @throws Error if JSON exceeds depth limit, size limit, or is invalid
223
+ * @security Do not disable depth checking without understanding XML bomb implications
224
+ *
225
+ * @example
226
+ * ```typescript
227
+ * // Standard parsing with default depth limit (100 levels)
228
+ * const data = safeJsonParse(jsonString);
229
+ *
230
+ * // Custom depth limit for data that needs deeper nesting
231
+ * const data = safeJsonParse(jsonString, 200); // 200 levels
232
+ * ```
233
+ */
234
+ declare function safeJsonParse(text: string, maxDepth?: number): unknown;
235
+
236
+ export { DEFAULT_LIMITS, cleanupFetchController, createFetchController, fetchWithTimeout, getHostnameFromUrl, getSafePath, isPathSafe, safeJsonParse, secureFetch, validateBufferSize, validateFileSize, validatePath, validatePathSimple, validateUrl };