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

354 lines (350 loc) 12.9 kB
import { builtinModules } from "module"; const DEFAULT_NODE_EXTERNALS = [ // Core Node.js modules ...builtinModules, ...builtinModules.map((mod) => `node:${mod}`), // Common server-only packages "fs-extra", "chokidar", "nodemon", "pm2", "sharp", "sqlite3", "mysql2", "pg", "mongodb", "redis", ]; const PLATFORM_CONFIGS = { cloudflare: { target: "es2022", format: "es", nodeCompat: false, maxSize: 1024 * 1024, // 1MB limit for free tier supportedAPIs: ["fetch", "WebSocket", "crypto", "streams"], }, vercel: { target: "es2020", format: "es", nodeCompat: true, maxSize: 4.5 * 1024 * 1024, // 4.5MB supportedAPIs: ["fetch", "crypto", "streams"], }, deno: { target: "es2022", format: "es", nodeCompat: true, maxSize: 50 * 1024 * 1024, // 50MB supportedAPIs: ["fetch", "WebSocket", "crypto", "streams"], }, netlify: { target: "es2020", format: "es", nodeCompat: true, maxSize: 6 * 1024 * 1024, // 6MB supportedAPIs: ["fetch", "crypto", "streams"], }, }; export function edgePlugin(options = {}) { const { platform = "cloudflare", entry = "src/main.ts", output = "dist/edge.js", minify = true, sourcemap = false, external = [], define = {}, target = PLATFORM_CONFIGS[platform].target, polyfills = true, frameworkName = "Pulzar", outDir = "dist", ssr = false, } = options; const platformConfig = PLATFORM_CONFIGS[platform]; const finalExternal = [...DEFAULT_NODE_EXTERNALS, ...external]; return { name: `${frameworkName.toLowerCase()}-edge`, config(config, { command }) { const isDev = command === "serve"; return { build: { target, minify: isDev ? false : minify, sourcemap: isDev ? true : sourcemap, outDir, ssr, rollupOptions: { input: entry, output: { file: output, format: platformConfig.format, exports: "named", // Add platform-specific output options ...(platform === "cloudflare" && { inlineDynamicImports: true, }), }, external: (id) => { // Check if it's a Node.js builtin if (finalExternal.includes(id)) return true; // Check for Node.js builtin with node: prefix if (id.startsWith("node:")) return true; // Platform-specific externals if (platform === "cloudflare") { // Cloudflare Workers don't support Node.js modules return builtinModules.includes(id) || id.startsWith("node:"); } if (platform === "vercel" || platform === "netlify") { // These platforms have some Node.js compatibility return finalExternal.includes(id); } if (platform === "deno") { // Deno has its own module system return finalExternal.includes(id) && !id.startsWith("https://"); } return false; }, plugins: [ // Add bundle analyzer in development ...(isDev ? [] : []), ], }, }, define: { "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || (isDev ? "development" : "production")), "process.env.PLATFORM": JSON.stringify(platform), "process.env.FRAMEWORK": JSON.stringify(frameworkName), ...(typeof window === "undefined" && { global: "globalThis" }), ...define, }, optimizeDeps: { // Exclude server-only dependencies from optimization exclude: finalExternal, }, }; }, transform(code, id) { // Only add polyfills to entry files and avoid SSR conflicts const isEntryFile = id.includes("main.ts") || id.includes("main.js") || id.includes("index.ts") || id.includes("index.js"); const shouldAddPolyfills = polyfills && isEntryFile && !ssr; if (shouldAddPolyfills) { const polyfillCode = getPlatformPolyfills(platform, frameworkName); return { code: polyfillCode + "\n" + code, map: null, }; } // Transform Node.js imports to edge-compatible ones if (platform === "cloudflare") { // Replace Node.js modules with Cloudflare Workers APIs const transformedCode = code .replace(/import\s+.*\s+from\s+['"]fs['"]/, "// fs module not available in Cloudflare Workers") .replace(/import\s+.*\s+from\s+['"]path['"]/, "// path module not available in Cloudflare Workers") .replace(/require\(['"]fs['"]\)/, "{}") .replace(/require\(['"]path['"]\)/, "{}"); if (transformedCode !== code) { return { code: transformedCode, map: null, }; } } return null; }, generateBundle(options, bundle) { // Add platform-specific wrapper for (const fileName in bundle) { const chunk = bundle[fileName]; if (chunk && chunk.type === "chunk" && chunk.isEntry) { const wrapper = getPlatformWrapper(platform, fileName, frameworkName); chunk.code = wrapper + "\n" + chunk.code; // Check bundle size limits const bundleSize = new TextEncoder().encode(chunk.code).length; if (bundleSize > platformConfig.maxSize) { this.warn(`Bundle size (${Math.round(bundleSize / 1024)}KB) exceeds ${platform} limit (${Math.round(platformConfig.maxSize / 1024)}KB). ` + `Consider code splitting or removing unused dependencies.`); } } } }, buildStart() { // Log platform configuration this.info(`Building for ${platform} with ${frameworkName}`); this.info(`Target: ${target}, Format: ${platformConfig.format}`); if (!platformConfig.nodeCompat) { this.warn(`${platform} has limited Node.js compatibility. Some features may not work.`); } }, buildEnd(error) { if (error) { this.error(`${frameworkName} edge build failed for ${platform}: ${error.message}`); } else { this.info(`${frameworkName} edge build completed for ${platform}`); } }, }; } function getPlatformPolyfills(platform, frameworkName) { const polyfills = { cloudflare: ` // ${frameworkName} Edge Runtime - Cloudflare Workers if (typeof global === 'undefined') { globalThis.global = globalThis; } if (typeof process === 'undefined') { globalThis.process = { env: {}, nextTick: (fn) => Promise.resolve().then(fn), platform: 'cloudflare', version: '${frameworkName.toLowerCase()}-edge-1.0.0' }; } `, vercel: ` // ${frameworkName} Edge Runtime - Vercel Edge Functions if (typeof global === 'undefined') { globalThis.global = globalThis; } if (typeof process === 'undefined') { globalThis.process = { env: {}, nextTick: (fn) => Promise.resolve().then(fn), platform: 'vercel', version: '${frameworkName.toLowerCase()}-edge-1.0.0' }; } `, deno: ` // ${frameworkName} Edge Runtime - Deno Deploy if (typeof global === 'undefined') { globalThis.global = globalThis; } if (typeof process === 'undefined') { globalThis.process = { env: typeof Deno !== 'undefined' ? Deno.env.toObject() : {}, nextTick: (fn) => Promise.resolve().then(fn), platform: 'deno', version: typeof Deno !== 'undefined' ? Deno.version.deno : '${frameworkName.toLowerCase()}-edge-1.0.0' }; } `, netlify: ` // ${frameworkName} Edge Runtime - Netlify Edge Functions if (typeof global === 'undefined') { globalThis.global = globalThis; } if (typeof process === 'undefined') { globalThis.process = { env: {}, nextTick: (fn) => Promise.resolve().then(fn), platform: 'netlify', version: '${frameworkName.toLowerCase()}-edge-1.0.0' }; } `, }; return polyfills[platform] || ""; } function getPlatformWrapper(platform, entryFile, frameworkName) { const wrappers = { cloudflare: ` // ${frameworkName} Cloudflare Workers Handler export default { async fetch(request, env, ctx) { try { const { default: app } = await import('./${entryFile}'); return await app(request, env, ctx); } catch (error) { console.error('${frameworkName} Cloudflare Workers Error:', error); return new Response(JSON.stringify({ error: 'Internal Server Error', framework: '${frameworkName}', platform: 'cloudflare' }), { status: 500, headers: { 'content-type': 'application/json' } }); } } }; `, vercel: ` // ${frameworkName} Vercel Edge Functions Handler try { const { default: app } = await import('./${entryFile}'); export default app; } catch (error) { console.error('${frameworkName} Vercel Error:', error); export default async (request) => { return new Response(JSON.stringify({ error: 'Internal Server Error', framework: '${frameworkName}', platform: 'vercel' }), { status: 500, headers: { 'content-type': 'application/json' } }); }; } `, deno: ` // ${frameworkName} Deno Deploy Handler try { const { default: app } = await import('./${entryFile}'); addEventListener('fetch', (event) => { event.respondWith(app(event.request)); }); } catch (error) { console.error('${frameworkName} Deno Error:', error); addEventListener('fetch', (event) => { event.respondWith(new Response(JSON.stringify({ error: 'Internal Server Error', framework: '${frameworkName}', platform: 'deno' }), { status: 500, headers: { 'content-type': 'application/json' } })); }); } `, netlify: ` // ${frameworkName} Netlify Edge Functions Handler try { const { default: app } = await import('./${entryFile}'); export default app; } catch (error) { console.error('${frameworkName} Netlify Error:', error); export default async (request, context) => { return new Response(JSON.stringify({ error: 'Internal Server Error', framework: '${frameworkName}', platform: 'netlify' }), { status: 500, headers: { 'content-type': 'application/json' } }); }; } `, }; return wrappers[platform] || ""; } export function createEdgeConfig(options = {}) { const platformConfig = PLATFORM_CONFIGS[options.platform || "cloudflare"]; return { plugins: [edgePlugin(options)], build: { target: options.target || platformConfig.target, minify: options.minify !== false, sourcemap: options.sourcemap || false, ssr: options.ssr || false, rollupOptions: { external: [...DEFAULT_NODE_EXTERNALS, ...(options.external || [])], }, }, define: { "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "production"), "process.env.PLATFORM": JSON.stringify(options.platform || "cloudflare"), "process.env.FRAMEWORK": JSON.stringify(options.frameworkName || "Pulzar"), global: "globalThis", ...(options.define || {}), }, }; } // Export utilities for advanced usage export { DEFAULT_NODE_EXTERNALS, PLATFORM_CONFIGS, getPlatformPolyfills, getPlatformWrapper, }; //# sourceMappingURL=vite-adapter.js.map