@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
JavaScript
/**
* 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