@sap/cds-dk
Version:
Command line client and development toolkit for the SAP Cloud Application Programming Model
77 lines (65 loc) • 2.55 kB
JavaScript
const cds = require('../../lib/cds')
const { pathToFileURL } = require('node:url')
const { path, stat, readdir, isdir, colors: { BOLD, RESET } } = cds.utils
let hmrPort = 24100
async function hasViteConfig(appPath) {
for (const name of ['vite.config.js', 'vite.config.mjs', 'vite.config.ts']) {
const file = await stat(path.join(appPath, name)).catch(e => e.code === 'ENOENT' ? null : Promise.reject(e))
return !!file
}
return false
}
async function findViteApps() {
const app = cds.env.folders.app
const apps = []
if (!isdir(app)) return apps
const entries = await readdir(app)
for (const entry of entries) {
const appName = typeof entry === 'string' ? entry : entry.name
if (!appName) continue
const appPath = path.join(cds.root, app, appName)
if (!isdir(appPath)) continue
if (await hasViteConfig(appPath)) apps.push({ name: appName, path: appPath })
}
return apps
}
async function loadCreateServer(fromPath) {
try {
const vitePath = require.resolve('vite', { paths: [fromPath] })
return (await import(pathToFileURL(vitePath).href)).createServer
} catch(e) {
if (e.code !== 'MODULE_NOT_FOUND') throw e
/* try next path */
}
const relative = path.relative(cds.root, fromPath)
throw `[cds] - Found Vite app in ${relative}, but package "vite" is not installed. Run ${BOLD}npm install vite --prefix ${relative}${RESET} to install it.`
}
cds.on('bootstrap', app => {
let viteMiddleware = null
app.use((req, res, next) => {
if (viteMiddleware) return viteMiddleware(req, res, next)
next()
})
cds.on('served', async () => {
const viteApps = await findViteApps()
if (!viteApps.length) return
const createServer = await loadCreateServer(viteApps[0].path)
// Build a middleware chain from all Vite servers, keyed by base path
const viteServers = []
const normalizeBase = base => {
if (!base.startsWith('/')) base = `/${base}`
return base.endsWith('/') ? base : `${base}/`
}
for (const viteApp of viteApps) {
const base = normalizeBase(viteApp.name)
const server = await createServer({ base, root: viteApp.path, server: { middlewareMode: true, hmr: { port: hmrPort++ } }})
viteServers.push({ base, middlewares: server.middlewares })
}
viteMiddleware = (req, res, next) => {
const url = req.url || ''
const match = viteServers.find(v => url.startsWith(v.base) || url.startsWith('/@'))
if (match) return match.middlewares(req, res, next)
next()
}
})
})