import react from '@vitejs/plugin-react'; import {readdirSync, readFileSync, statSync} from 'node:fs'; import {extname, resolve, sep} from 'node:path'; import {fileURLToPath, URL} from 'node:url'; import {defineConfig, type Plugin} from 'vite'; const output_dir = fileURLToPath(new URL('../frontend_dist', import.meta.url)); const cache_dir = fileURLToPath(new URL('./node_modules/.vite-adminive', import.meta.url)); const amis_sdk_dir = fileURLToPath(new URL('./node_modules/amis/sdk', import.meta.url)); const amis_package = JSON.parse(readFileSync(fileURLToPath(new URL('./node_modules/amis/package.json', import.meta.url)), 'utf8')) as {version: string}; const amis_sdk_url_prefix = `/vendor/amis/${amis_package.version}/`; function content_type(file_name: string) { switch(extname(file_name).toLowerCase()) { case '.css': return 'text/css; charset=utf-8'; case '.js': return 'text/javascript; charset=utf-8'; case '.json': return 'application/json; charset=utf-8'; case '.svg': return 'image/svg+xml'; case '.woff': return 'font/woff'; case '.woff2': return 'font/woff2'; case '.ttf': return 'font/ttf'; default: return 'application/octet-stream'; } } function amis_sdk_plugin(): Plugin { return { name: 'adminive-amis-sdk', enforce: 'pre', resolveId(source) { if(source === 'amis' || source.startsWith('amis/')) { this.error(`Do not import ${source} into the Adminive Vite module graph; use the AMIS SDK runtime instead`); } return null; }, buildStart() { const emit_directory = (directory: string, prefix: string) => { for(const entry of readdirSync(directory)) { const source_path = resolve(directory, entry); const relative_path = `${prefix}${entry}`; if(statSync(source_path).isDirectory()) { emit_directory(source_path, `${relative_path}/`); continue; } this.emitFile({ type: 'asset', fileName: `vendor/amis/${amis_package.version}/${relative_path}`, source: readFileSync(source_path) }); } }; emit_directory(amis_sdk_dir, ''); }, transformIndexHtml: { order: 'post', handler() { return [ {tag: 'link', attrs: {rel: 'stylesheet', href: `${amis_sdk_url_prefix}sdk.css`}, injectTo: 'head-prepend'}, {tag: 'link', attrs: {rel: 'stylesheet', href: `${amis_sdk_url_prefix}helper.css`}, injectTo: 'head-prepend'}, {tag: 'link', attrs: {rel: 'stylesheet', href: `${amis_sdk_url_prefix}iconfont.css`}, injectTo: 'head-prepend'}, {tag: 'script', attrs: {src: `${amis_sdk_url_prefix}sdk.js`}, injectTo: 'head-prepend'} ]; } }, configureServer(server) { server.middlewares.use((request, response, next) => { const pathname = new URL(request.url ?? '/', 'http://localhost').pathname; if(!pathname.startsWith(amis_sdk_url_prefix)) { next(); return; } const relative_path = decodeURIComponent(pathname.slice(amis_sdk_url_prefix.length)); const source_path = resolve(amis_sdk_dir, relative_path); if(source_path !== amis_sdk_dir && !source_path.startsWith(`${amis_sdk_dir}${sep}`)) { next(); return; } try { const source = readFileSync(source_path); response.statusCode = 200; response.setHeader('Content-Type', content_type(source_path)); response.end(source); } catch { next(); } }); }, configurePreviewServer(server) { server.middlewares.use((request, response, next) => { const pathname = new URL(request.url ?? '/', 'http://localhost').pathname; if(!pathname.startsWith(amis_sdk_url_prefix)) { next(); return; } const relative_path = decodeURIComponent(pathname.slice(amis_sdk_url_prefix.length)); const source_path = resolve(amis_sdk_dir, relative_path); if(source_path !== amis_sdk_dir && !source_path.startsWith(`${amis_sdk_dir}${sep}`)) { next(); return; } try { const source = readFileSync(source_path); response.statusCode = 200; response.setHeader('Content-Type', content_type(source_path)); response.end(source); } catch { next(); } }); } }; } export default defineConfig({ cacheDir: cache_dir, plugins: [react(), amis_sdk_plugin()], resolve: { dedupe: ['react', 'react-dom'] }, server: { host: '0.0.0.0', port: 5173, proxy: { '/admin': { target: 'http://127.0.0.1:9999', changeOrigin: true } } }, build: { outDir: output_dir, emptyOutDir: true } });