mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
4b86ff73cf
Run the dev API on 6262 and Vite on 6263 with strictPort; production defaults stay on 3000. Define the dev client origin once and read the typed appConfig instead of repeating its fallback in every gateway.
169 lines
4.7 KiB
TypeScript
169 lines
4.7 KiB
TypeScript
import { fileURLToPath, URL } from 'node:url'
|
|
import { Agent } from 'node:http'
|
|
|
|
import { defineConfig } from 'vite'
|
|
import vue from '@vitejs/plugin-vue'
|
|
import vueDevTools from 'vite-plugin-vue-devtools'
|
|
import tailwindcss from '@tailwindcss/vite'
|
|
import { VitePWA } from 'vite-plugin-pwa'
|
|
|
|
const apiAgent = new Agent({ keepAlive: true })
|
|
/** Lets a second dev client point at a throwaway API instance, so restart testing leaves the main stack alone. */
|
|
const apiTarget = process.env.BOOKORBIT_API_TARGET ?? 'http://localhost:6262'
|
|
|
|
// https://vite.dev/config/
|
|
export default defineConfig({
|
|
define: {
|
|
__INTLIFY_PROD_DEVTOOLS__: false,
|
|
__VUE_I18N_FULL_INSTALL__: true,
|
|
__VUE_I18N_LEGACY_API__: false,
|
|
},
|
|
plugins: [
|
|
vue(),
|
|
vueDevTools(),
|
|
tailwindcss(),
|
|
VitePWA({
|
|
registerType: 'autoUpdate',
|
|
injectRegister: 'auto',
|
|
includeAssets: [
|
|
'favicon.ico',
|
|
'pwa-icon-source.svg',
|
|
'apple-touch-icon-180x180.png',
|
|
'pwa-64x64.png',
|
|
'pwa-192x192.png',
|
|
'pwa-512x512.png',
|
|
'maskable-icon-512x512.png',
|
|
],
|
|
manifest: {
|
|
name: 'BookOrbit',
|
|
short_name: 'BookOrbit',
|
|
description: 'Your personal book library and reading space',
|
|
theme_color: '#1e1e18',
|
|
background_color: '#fafaf8',
|
|
display: 'standalone',
|
|
start_url: '/',
|
|
scope: '/',
|
|
icons: [
|
|
{
|
|
src: 'pwa-64x64.png',
|
|
sizes: '64x64',
|
|
type: 'image/png',
|
|
},
|
|
{
|
|
src: 'pwa-192x192.png',
|
|
sizes: '192x192',
|
|
type: 'image/png',
|
|
},
|
|
{
|
|
src: 'pwa-512x512.png',
|
|
sizes: '512x512',
|
|
type: 'image/png',
|
|
},
|
|
{
|
|
src: 'maskable-icon-512x512.png',
|
|
sizes: '512x512',
|
|
type: 'image/png',
|
|
purpose: 'maskable',
|
|
},
|
|
],
|
|
shortcuts: [
|
|
{
|
|
name: 'Dashboard',
|
|
short_name: 'Dashboard',
|
|
url: '/dashboard',
|
|
icons: [{ src: 'pwa-192x192.png', sizes: '192x192' }],
|
|
},
|
|
{
|
|
name: 'Libraries',
|
|
short_name: 'Libraries',
|
|
url: '/libraries',
|
|
icons: [{ src: 'pwa-192x192.png', sizes: '192x192' }],
|
|
},
|
|
{
|
|
name: 'Settings',
|
|
short_name: 'Settings',
|
|
url: '/settings',
|
|
icons: [{ src: 'pwa-192x192.png', sizes: '192x192' }],
|
|
},
|
|
],
|
|
},
|
|
workbox: {
|
|
globPatterns: ['**/*.{js,css,html,ico,png,svg,woff,woff2}'],
|
|
globIgnores: ['**/assets/foliate/**'],
|
|
navigateFallback: 'index.html',
|
|
navigateFallbackDenylist: [/^\/api\//],
|
|
runtimeCaching: [
|
|
{
|
|
urlPattern: /^.*\/api\/v1\/books\/\d+\/cover(\?.*)?$/,
|
|
handler: 'CacheFirst',
|
|
options: {
|
|
cacheName: 'book-covers',
|
|
expiration: {
|
|
maxEntries: 200,
|
|
maxAgeSeconds: 60 * 60 * 24 * 30,
|
|
},
|
|
cacheableResponse: {
|
|
statuses: [0, 200],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
urlPattern: /^.*\/api\/v1\/books\/\d+\/thumbnail(\?.*)?$/,
|
|
handler: 'CacheFirst',
|
|
options: {
|
|
cacheName: 'book-thumbnails',
|
|
expiration: {
|
|
maxEntries: 200,
|
|
maxAgeSeconds: 60 * 60 * 24 * 30,
|
|
},
|
|
cacheableResponse: {
|
|
statuses: [0, 200],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
devOptions: {
|
|
enabled: false,
|
|
type: 'module',
|
|
},
|
|
}),
|
|
],
|
|
resolve: {
|
|
dedupe: ['vue'],
|
|
alias: {
|
|
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|
'@bookorbit/types': fileURLToPath(new URL('../packages/types/src/index.ts', import.meta.url)),
|
|
},
|
|
},
|
|
optimizeDeps: {
|
|
include: ['@tanstack/vue-virtual'],
|
|
exclude: ['@embedpdf/core', '@embedpdf/core/vue'],
|
|
},
|
|
server: {
|
|
port: 6263,
|
|
strictPort: true,
|
|
host: true,
|
|
allowedHosts: true,
|
|
proxy: {
|
|
'/api': {
|
|
target: apiTarget,
|
|
agent: apiAgent,
|
|
configure: (proxy) => {
|
|
proxy.on('proxyReq', (proxyReq, req) => {
|
|
if (req.headers.host) proxyReq.setHeader('x-forwarded-host', req.headers.host)
|
|
const localPort = (req.socket as { localPort?: number })?.localPort
|
|
if (localPort) proxyReq.setHeader('x-forwarded-port', String(localPort))
|
|
proxyReq.setHeader('x-forwarded-proto', 'http')
|
|
})
|
|
},
|
|
},
|
|
'/socket.io': {
|
|
target: apiTarget,
|
|
ws: true,
|
|
changeOrigin: true,
|
|
},
|
|
},
|
|
},
|
|
})
|