@dbs-portal/tool-mock
Version:
API mocking toolkit using MSW for DBS Portal development workflows
251 lines (243 loc) • 7.87 kB
JavaScript
/**
* Development server utilities for MSW integration
*/
import { setupMocks } from '../core/setup';
/**
* Create development server configuration with MSW support
*/
export function createMSWDevServerConfig(config = {}) {
const { port = 3000, host = 'localhost', https = false, cors = true, proxy = {}, mswConfig = {}, hotReload = {}, } = config;
return {
server: {
port,
host,
https,
cors,
proxy,
// Configure middleware for MSW
middlewareMode: false,
// Custom middleware
configureServer: (server) => {
// Setup MSW if enabled
if (mswConfig.enabled !== false) {
setupMSWMiddleware(server, mswConfig);
}
// Setup hot reload if enabled
if (hotReload.enabled !== false) {
setupHotReloadMiddleware(server, hotReload);
}
},
},
// Optimizations for development
optimizeDeps: {
include: ['msw'],
exclude: ['@dbs-portal/tool-mock'],
},
// Define environment variables
define: {
__MSW_ENABLED__: JSON.stringify(mswConfig.enabled !== false),
__MSW_LOGGING__: JSON.stringify(mswConfig.logging !== false),
},
};
}
/**
* Setup MSW middleware for development server
*/
function setupMSWMiddleware(server, config) {
const { handlers = [], logging = true, delay = [100, 300] } = config;
// Serve MSW service worker
server.middlewares.use('/mockServiceWorker.js', (req, res) => {
if (req.method === 'GET') {
res.setHeader('Content-Type', 'application/javascript');
res.setHeader('Service-Worker-Allowed', '/');
const serviceWorkerContent = generateDevServiceWorkerContent();
res.end(serviceWorkerContent);
if (logging) {
console.log('MSW: Served service worker');
}
}
});
// Add MSW status endpoint
server.middlewares.use('/api/__msw/status', (req, res) => {
if (req.method === 'GET') {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
enabled: true,
mode: 'development',
handlersCount: handlers.length,
delay,
timestamp: new Date().toISOString(),
}));
}
});
// Add MSW control endpoints
server.middlewares.use('/api/__msw/reload', (req, res) => {
if (req.method === 'POST') {
// Trigger MSW reload
server.ws.send({
type: 'custom',
event: 'msw:reload',
data: { timestamp: Date.now() },
});
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ success: true }));
if (logging) {
console.log('MSW: Handlers reloaded');
}
}
});
if (logging) {
console.log('MSW: Development middleware configured');
}
}
/**
* Setup hot reload middleware for mock files
*/
function setupHotReloadMiddleware(server, config) {
const { watchPaths = ['src/**/*mock*', 'src/**/*handler*'], debounceDelay = 300, } = config;
let reloadTimeout = null;
// Watch for file changes
server.watcher.on('change', (filePath) => {
const shouldReload = watchPaths.some((pattern) => {
// Simple pattern matching (in real implementation, use glob)
return filePath.includes(pattern.replace('*', ''));
});
if (shouldReload) {
// Debounce reload
if (reloadTimeout) {
clearTimeout(reloadTimeout);
}
reloadTimeout = setTimeout(() => {
server.ws.send({
type: 'custom',
event: 'msw:file-changed',
data: { filePath, timestamp: Date.now() },
});
console.log(`MSW: Mock file changed: ${filePath}`);
}, debounceDelay);
}
});
console.log('MSW: Hot reload middleware configured');
}
/**
* Generate service worker content for development
*/
function generateDevServiceWorkerContent() {
return `
/**
* MSW Development Service Worker
*/
importScripts('https://unpkg.com/msw@2.6.4/lib/mockServiceWorker.js');
// Development-specific features
self.addEventListener('message', async function (event) {
const { type, payload } = event.data;
switch (type) {
case 'MOCK_ACTIVATE': {
console.log('MSW: Activating mock service worker');
self.registration.addEventListener('activate', () => {
event.ports[0].postMessage({ type: 'MOCK_ACTIVATED' });
});
break;
}
case 'MOCK_DEACTIVATE': {
console.log('MSW: Deactivating mock service worker');
await self.registration.unregister();
event.ports[0].postMessage({ type: 'MOCK_DEACTIVATED' });
break;
}
case 'MOCK_RELOAD': {
console.log('MSW: Reloading handlers');
// Trigger reload
self.clients.matchAll().then(clients => {
clients.forEach(client => {
client.postMessage({ type: 'MSW_RELOAD' });
});
});
break;
}
default: {
// Forward to MSW
break;
}
}
});
// Log requests in development
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('/api/')) {
console.log('MSW: Intercepting request:', event.request.method, event.request.url);
}
});
console.log('MSW: Development service worker loaded');
`;
}
/**
* Development server utilities
*/
export const devServerUtils = {
/**
* Create proxy configuration for API endpoints
*/
createApiProxy: (apiBaseUrl) => ({
'/api': {
target: apiBaseUrl,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
}),
/**
* Create CORS configuration for development
*/
createCorsConfig: (allowedOrigins = ['http://localhost:3000']) => ({
origin: allowedOrigins,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
credentials: true,
}),
/**
* Create development environment variables
*/
createDevEnvVars: (config = {}) => ({
__DEV__: true,
__MSW_ENABLED__: config.mswEnabled !== false,
__MSW_LOGGING__: config.mswLogging !== false,
__API_BASE_URL__: config.apiBaseUrl || '/api',
}),
};
/**
* Start development server with MSW
*/
export async function startDevServerWithMSW(config = {}) {
console.log('Starting development server with MSW support...');
// Setup MSW first
if (config.mswConfig?.enabled !== false) {
await setupMocks({
config: {
enabled: true,
mode: 'development',
logging: config.mswConfig?.logging !== false,
delay: config.mswConfig?.delay || [100, 300],
},
handlers: config.mswConfig?.handlers || [],
});
}
console.log('MSW development server ready!');
}
/**
* Development server health check
*/
export function createHealthCheck() {
return {
'/api/__health': (_req, res) => {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
status: 'healthy',
timestamp: new Date().toISOString(),
services: {
msw: true,
api: true,
},
}));
},
};
}
//# sourceMappingURL=dev-server.js.map