@dbs-portal/core-api
Version:
HTTP client and API utilities for DBS Portal
232 lines (209 loc) • 6.47 kB
JavaScript
/**
* Vite plugin for MSW integration
*/
const { VITE_NODE_ENV: NODE_ENV } = import.meta.env;
/**
* Create MSW Vite plugin
*/
export function mswPlugin(options = {}) {
const { enabled = true, mode = 'development', publicDir = 'public', serviceWorkerFilename = 'mockServiceWorker.js', autoGenerateServiceWorker = true, verbose = false, } = options;
return {
name: 'msw-integration',
configResolved(config) {
if (!enabled)
return;
// Add MSW environment variables
config = {
...config,
define: {
...config.define,
__MSW_ENABLED__: JSON.stringify(enabled),
__MSW_MODE__: JSON.stringify(mode),
}
};
if (verbose) {
console.log(`[MSW Plugin] Enabled in ${mode} mode`);
}
},
async buildStart() {
if (!enabled || !autoGenerateServiceWorker)
return;
// Only run in Node environment
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
const { existsSync, writeFileSync } = await import('fs');
const { resolve } = await import('path');
const serviceWorkerPath = resolve(publicDir, serviceWorkerFilename);
// Check if service worker exists
if (!existsSync(serviceWorkerPath)) {
if (verbose) {
console.log(`[MSW Plugin] Generating service worker at ${serviceWorkerPath}`);
}
// Generate basic service worker
generateServiceWorker(serviceWorkerPath, writeFileSync);
}
}
},
configureServer(server) {
if (!enabled)
return;
// Add middleware to serve MSW service worker
server.middlewares.use(`/${serviceWorkerFilename}`, async (_req, res, next) => {
try {
const { existsSync, readFileSync } = await import('fs');
const { resolve } = await import('path');
const serviceWorkerPath = resolve(publicDir, serviceWorkerFilename);
if (existsSync(serviceWorkerPath)) {
const content = readFileSync(serviceWorkerPath, 'utf-8');
res.setHeader('Content-Type', 'application/javascript');
res.setHeader('Service-Worker-Allowed', '/');
res.end(content);
}
else {
next();
}
}
catch (error) {
next(error);
}
});
if (verbose) {
console.log(`[MSW Plugin] Service worker available at /${serviceWorkerFilename}`);
}
},
};
}
/**
* Generate basic MSW service worker
*/
function generateServiceWorker(filePath, writeFileSync) {
const serviceWorkerContent = `
/**
* Mock Service Worker (MSW) Service Worker
* Generated automatically by @dbs-portal/core-api MSW plugin
*/
/* eslint-disable */
/* tslint:disable */
const INTEGRITY_CHECKSUM = '02f4ad4a2ca266d84b5226dda4ca245d'
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
const activeClientIds = new Set()
self.addEventListener('install', function () {
self.skipWaiting()
})
self.addEventListener('activate', function (event) {
event.waitUntil(self.clients.claim())
})
self.addEventListener('message', async function (event) {
const clientId = event.source.id
if (!clientId || !event.data) {
return
}
const allClients = await self.clients.matchAll({
type: 'window',
})
switch (event.data.type) {
case 'KEEPALIVE_REQUEST': {
sendToClient(event.source, {
type: 'KEEPALIVE_RESPONSE',
payload: Date.now(),
})
break
}
case 'INTEGRITY_CHECK_REQUEST': {
sendToClient(event.source, {
type: 'INTEGRITY_CHECK_RESPONSE',
payload: INTEGRITY_CHECKSUM,
})
break
}
case 'MOCK_ACTIVATE': {
activeClientIds.add(clientId)
sendToClient(event.source, {
type: 'MOCKING_ENABLED',
payload: true,
})
break
}
case 'MOCK_DEACTIVATE': {
activeClientIds.delete(clientId)
break
}
case 'CLIENT_CLOSED': {
activeClientIds.delete(clientId)
const remainingClients = allClients.filter((client) => {
return client.id !== clientId
})
if (remainingClients.length === 0) {
self.registration.unregister()
}
break
}
}
})
self.addEventListener('fetch', function (event) {
const { request } = event
const accept = request.headers.get('accept') || ''
if (
request.method !== 'GET' ||
!accept.includes('text/html')
) {
return
}
event.respondWith(
fetch(request).catch(() => {
return new Response(
JSON.stringify({
error: 'Network request failed',
message: 'MSW service worker intercepted a failed request',
}),
{
status: 500,
headers: {
'Content-Type': 'application/json',
},
}
)
})
)
})
function sendToClient(client, message) {
return new Promise((resolve, reject) => {
const channel = new MessageChannel()
channel.port1.onmessage = (event) => {
if (event.data && event.data.error) {
return reject(event.data.error)
}
resolve(event.data)
}
client.postMessage(message, [channel.port2])
})
}
`.trim();
writeFileSync(filePath, serviceWorkerContent, 'utf-8');
}
/**
* Default MSW plugin for development
*/
export const mswDevelopmentPlugin = () => mswPlugin({
enabled: NODE_ENV === 'development',
mode: 'development',
verbose: true,
});
/**
* MSW plugin for testing
*/
export const mswTestingPlugin = () => mswPlugin({
enabled: NODE_ENV === 'test',
mode: 'testing',
autoGenerateServiceWorker: false, // Not needed for Node.js tests
verbose: false,
});
/**
* MSW plugin for Storybook
*/
export const mswStorybookPlugin = () => mswPlugin({
enabled: true,
mode: 'storybook',
publicDir: '.storybook/public',
verbose: true,
});
//# sourceMappingURL=vite-plugin.js.map