Files
shelfless/vite.config.ts
Scarriffle 83d8b7b99d Initial commit: Shelfless – alternative Audiobookshelf frontend
React + Vite + TypeScript SPA covering the full ABS feature set (library
browsing, item detail, metadata/cover editing, podcasts, player with session
sync, admin: users/libraries/scanner/server settings). Dev uses a dynamic
CORS proxy; production is served by server/index.mjs (static + reverse proxy
to ABS_URL). Includes systemd unit and installer under deploy/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 20:23:04 +02:00

74 lines
2.2 KiB
TypeScript

import { defineConfig, type Plugin } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'node:path'
import http from 'node:http'
import https from 'node:https'
/**
* Dev-only dynamic proxy. The browser can't call an arbitrary ABS server directly
* (it sends no CORS headers), so in dev the client routes every ABS request through
* `/__abs/<url-encoded-server>/<path>`. This middleware decodes the target from the
* path and forwards the request server-side — no CORS, and the target can change at
* runtime (just log in to a different server). Production needs a real reverse proxy.
*/
function dynamicAbsProxy(): Plugin {
return {
name: 'shelfless-dynamic-abs-proxy',
configureServer(server) {
server.middlewares.use((req, res, next) => {
if (!req.url?.startsWith('/__abs/')) return next()
const m = req.url.match(/^\/__abs\/([^/]+)(.*)$/)
if (!m) {
res.statusCode = 400
return res.end('Bad proxy path')
}
let target: URL
try {
target = new URL(decodeURIComponent(m[1]))
} catch {
res.statusCode = 400
return res.end('Bad proxy target')
}
const isHttps = target.protocol === 'https:'
const lib = isHttps ? https : http
const headers = { ...req.headers, host: target.host }
delete headers.origin
delete headers.referer
const proxyReq = lib.request(
{
protocol: target.protocol,
hostname: target.hostname,
port: target.port || (isHttps ? 443 : 80),
method: req.method,
path: m[2] || '/',
headers,
},
(proxyRes) => {
res.writeHead(proxyRes.statusCode || 502, proxyRes.headers)
proxyRes.pipe(res)
},
)
proxyReq.on('error', (e) => {
res.statusCode = 502
res.end(`Proxy error: ${e.message}`)
})
req.pipe(proxyReq)
})
},
}
}
// https://vite.dev/config/
export default defineConfig({
plugins: [react(), dynamicAbsProxy()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
server: {
port: 5173,
},
})