UNPKG

@pulzar/core

Version:

Next-generation Node.js framework for ultra-fast web applications with zero-reflection DI, GraphQL, WebSockets, events, and edge runtime support

247 lines 8.47 kB
/** * Minimal Edge Runtime Polyfills * Provides essential compatibility shims for Node.js APIs in edge environments * Optimized for size and security */ // Only add polyfills if they don't exist const isEdgeRuntime = typeof window === "undefined" && typeof self !== "undefined"; // Minimal process polyfill if (typeof process === "undefined") { globalThis.process = { env: {}, nextTick: (fn) => Promise.resolve().then(() => fn()), platform: "edge", version: "1.0.0", versions: { node: "1.0.0" }, cwd: () => "/", exit: () => { }, on: () => { }, once: () => { }, emit: () => false, removeListener: () => { }, removeAllListeners: () => { }, }; } // Minimal Buffer polyfill (only if needed) if (typeof Buffer === "undefined") { const BufferPolyfill = { from: (data, encoding) => { if (typeof data === "string") { return new TextEncoder().encode(data); } if (ArrayBuffer.isView(data)) { return new Uint8Array(data.buffer, data.byteOffset, data.byteLength); } if (data instanceof ArrayBuffer) { return new Uint8Array(data); } if (Array.isArray(data)) { return new Uint8Array(data); } return new Uint8Array(0); }, alloc: (size, fill) => { const buffer = new Uint8Array(size); if (fill !== undefined) { if (typeof fill === "number") { buffer.fill(fill); } else if (typeof fill === "string") { const fillBytes = new TextEncoder().encode(fill); for (let i = 0; i < size; i++) { buffer[i] = fillBytes[i % fillBytes.length]; } } } return buffer; }, allocUnsafe: (size) => new Uint8Array(size), isBuffer: (obj) => obj instanceof Uint8Array, concat: (list, totalLength) => { if (totalLength === undefined) { totalLength = list.reduce((acc, buf) => acc + buf.length, 0); } const result = new Uint8Array(totalLength); let offset = 0; for (const buf of list) { result.set(buf, offset); offset += buf.length; } return result; }, }; globalThis.Buffer = BufferPolyfill; } // Use native crypto if available, otherwise provide minimal interface if (typeof crypto === "undefined" || !crypto.getRandomValues) { const cryptoPolyfill = { getRandomValues: (array) => { // Use Math.random as fallback (not cryptographically secure!) console.warn("Using non-cryptographically secure random values. Use a proper crypto library in production."); for (let i = 0; i < array.length; i++) { array[i] = Math.floor(Math.random() * 256); } return array; }, randomUUID: () => { // Simple UUID v4 generation (not cryptographically secure) console.warn("Using non-cryptographically secure UUID generation. Use a proper crypto library in production."); return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { const r = (Math.random() * 16) | 0; const v = c === "x" ? r : (r & 0x3) | 0x8; return v.toString(16); }); }, // For digest, recommend using platform-specific implementations subtle: { digest: async () => { throw new Error("crypto.subtle.digest not available. Use platform-specific crypto implementations."); }, }, }; if (typeof crypto === "undefined") { globalThis.crypto = cryptoPolyfill; } else { // Extend existing crypto if it's incomplete if (!crypto.getRandomValues) { crypto.getRandomValues = cryptoPolyfill.getRandomValues; } if (!crypto.randomUUID) { crypto.randomUUID = cryptoPolyfill.randomUUID; } } } // Minimal console polyfill (if needed) if (typeof console === "undefined") { globalThis.console = { log: (...args) => { }, info: (...args) => { }, warn: (...args) => { }, error: (...args) => { }, debug: (...args) => { }, trace: (...args) => { }, time: () => { }, timeEnd: () => { }, group: () => { }, groupEnd: () => { }, clear: () => { }, count: () => { }, assert: () => { }, dir: () => { }, table: () => { }, }; } // Platform-specific optimizations const platformPolyfills = { cloudflare: () => { // Cloudflare Workers already have most APIs if (typeof global === "undefined") { globalThis.global = globalThis; } }, vercel: () => { // Vercel Edge already has most APIs if (typeof global === "undefined") { globalThis.global = globalThis; } }, deno: () => { // Deno has excellent standard library, minimal polyfills needed if (typeof process !== "undefined" && typeof globalThis.Deno !== "undefined") { // Enhance process.env with Deno.env if available try { const deno = globalThis.Deno; if (deno?.env?.toObject) { process.env = { ...process.env, ...deno.env.toObject() }; } } catch { // Deno.env might not be available in all contexts } } }, netlify: () => { // Netlify Edge Functions have good compatibility if (typeof global === "undefined") { globalThis.global = globalThis; } }, }; /** * Apply platform-specific polyfills */ export function applyPlatformPolyfills(platform) { const polyfillFn = platformPolyfills[platform]; if (polyfillFn) { polyfillFn(); } } /** * Check if we're running in an edge environment */ export function isEdgeEnvironment() { return (typeof window === "undefined" && (typeof self !== "undefined" || typeof global !== "undefined") && typeof process?.versions?.node === "undefined"); } /** * Get platform-specific feature availability */ export function getPlatformFeatures() { return { hasWebStreams: typeof ReadableStream !== "undefined", hasWebCrypto: typeof crypto !== "undefined" && typeof crypto.subtle !== "undefined", hasTextEncoder: typeof TextEncoder !== "undefined", hasTextDecoder: typeof TextDecoder !== "undefined", hasURL: typeof URL !== "undefined", hasURLSearchParams: typeof URLSearchParams !== "undefined", hasHeaders: typeof Headers !== "undefined", hasRequest: typeof Request !== "undefined", hasResponse: typeof Response !== "undefined", hasFetch: typeof fetch !== "undefined", hasWebSocket: typeof WebSocket !== "undefined", }; } /** * Validate edge environment capabilities */ export function validateEdgeEnvironment() { const features = getPlatformFeatures(); const required = ["hasTextEncoder", "hasURL", "hasResponse"]; const missing = []; for (const feature of required) { if (!features[feature]) { missing.push(feature.replace("has", "")); } } return { compatible: missing.length === 0, missing, }; } // Auto-apply polyfills based on detected platform if (isEdgeRuntime) { // Try to detect platform and apply appropriate polyfills if (typeof navigator !== "undefined" && navigator.userAgent?.includes("Cloudflare-Workers")) { applyPlatformPolyfills("cloudflare"); } else if (typeof process?.env?.VERCEL !== "undefined") { applyPlatformPolyfills("vercel"); } else if (typeof globalThis.Deno !== "undefined") { applyPlatformPolyfills("deno"); } else if (typeof process?.env?.NETLIFY !== "undefined") { applyPlatformPolyfills("netlify"); } } export default { applyPlatformPolyfills, isEdgeEnvironment, getPlatformFeatures, validateEdgeEnvironment, }; //# sourceMappingURL=polyfills.js.map