110 lines
3.8 KiB
TypeScript
110 lines
3.8 KiB
TypeScript
import http from 'node:http'
|
|
import https from 'node:https'
|
|
import tailwindcss from '@tailwindcss/vite'
|
|
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
|
|
import viteReact from '@vitejs/plugin-react'
|
|
import { defineConfig, type Plugin } from 'vite'
|
|
import tsconfigPaths from 'vite-tsconfig-paths'
|
|
import { nitro } from 'nitro/vite'
|
|
|
|
const flattenPlugins = (plugins: Array<unknown>): Plugin[] =>
|
|
plugins.flat(Infinity).filter((plugin): plugin is Plugin => Boolean(plugin))
|
|
|
|
type BuildWarning = { code?: string; id?: string; message: string }
|
|
|
|
function warnBuild(warning: BuildWarning, warn: (warning: BuildWarning) => void) {
|
|
const dependency = warning.id?.includes('/node_modules/') ?? false
|
|
const knownDependencyNoise = (
|
|
(dependency && warning.code === 'MODULE_LEVEL_DIRECTIVE' && warning.message.includes('use client'))
|
|
|| (warning.code === 'UNUSED_EXTERNAL_IMPORT' && warning.message.includes('@tanstack/'))
|
|
)
|
|
if (!knownDependencyNoise) warn(warning)
|
|
}
|
|
|
|
const rollupWarningOptions = { onwarn: warnBuild }
|
|
|
|
function creatorHubBuildWarningPlugin(): Plugin {
|
|
return {
|
|
name: 'creatorhub:build-warning-filter',
|
|
config() {
|
|
return {
|
|
environments: {
|
|
ssr: { build: { rollupOptions: rollupWarningOptions } },
|
|
},
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
function creatorHubAssetFetchDest(): Plugin {
|
|
return {
|
|
name: 'creatorhub:asset-fetch-dest',
|
|
enforce: 'pre',
|
|
configureServer(server) {
|
|
server.middlewares.use((request, _response, next) => {
|
|
// Chromium can omit Fetch Metadata for LAN requests; Nitro otherwise treats these assets as document routes.
|
|
if (request.headers['sec-fetch-dest']) return next()
|
|
const pathname = request.url?.split(/[?#]/, 1)[0] ?? ''
|
|
if (/\.css$/.test(pathname)) request.headers['sec-fetch-dest'] = 'style'
|
|
else if (/\.(?:[cm]?[jt]sx?|mjs)$/.test(pathname)) request.headers['sec-fetch-dest'] = 'script'
|
|
next()
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
function creatorHubApiProxy(): Plugin {
|
|
const target = process.env.CREATORHUB_CONTROL_PLANE_URL ?? 'http://127.0.0.1:8082'
|
|
return {
|
|
name: 'creatorhub:control-plane-proxy',
|
|
configureServer(server) {
|
|
server.middlewares.use((request, response, next) => {
|
|
if (!request.url?.startsWith('/api/')) return next()
|
|
const upstreamURL = new URL(request.url, target)
|
|
const transport = upstreamURL.protocol === 'https:' ? https : http
|
|
const headers = { ...request.headers, host: upstreamURL.host }
|
|
const upstream = transport.request(upstreamURL, { method: request.method, headers }, (upstreamResponse) => {
|
|
response.statusCode = upstreamResponse.statusCode ?? 502
|
|
for (const [name, value] of Object.entries(upstreamResponse.headers)) {
|
|
if (value !== undefined) response.setHeader(name, value)
|
|
}
|
|
upstreamResponse.pipe(response)
|
|
})
|
|
upstream.on('error', (error) => {
|
|
server.config.logger.error(`[creatorhub:control-plane-proxy] ${request.method ?? 'GET'} ${request.url}: ${error.message}`)
|
|
if (!response.headersSent) {
|
|
response.statusCode = 502
|
|
response.setHeader('content-type', 'application/json')
|
|
response.end(JSON.stringify({ error: '控制面代理不可用' }))
|
|
} else {
|
|
response.destroy(error)
|
|
}
|
|
})
|
|
request.pipe(upstream)
|
|
})
|
|
},
|
|
}
|
|
}
|
|
|
|
export default defineConfig({
|
|
server: {
|
|
host: true,
|
|
port: 5100,
|
|
strictPort: true,
|
|
proxy: { '/api': 'http://127.0.0.1:8082' }
|
|
},
|
|
build: {
|
|
rollupOptions: rollupWarningOptions
|
|
},
|
|
plugins: flattenPlugins([
|
|
creatorHubAssetFetchDest(),
|
|
creatorHubApiProxy(),
|
|
tsconfigPaths(),
|
|
tailwindcss(),
|
|
tanstackStart(),
|
|
creatorHubBuildWarningPlugin(),
|
|
nitro({ preset: process.env.SERVER_PRESET, rollupConfig: rollupWarningOptions }),
|
|
viteReact()
|
|
])
|
|
})
|