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