diff --git a/backend/main.py b/backend/main.py index 198d8b26..df34810b 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,10 +1,7 @@ import logging from fastapi.concurrency import asynccontextmanager -from fastapi.responses import FileResponse -from fastapi.staticfiles import StaticFiles -import os import sentry_sdk -from fastapi import FastAPI, Path, HTTPException +from fastapi import FastAPI from fastapi.routing import APIRoute from starlette.middleware.cors import CORSMiddleware from starlette.exceptions import HTTPException as StarletteHTTPException @@ -76,19 +73,7 @@ app.include_router(api_router, prefix=settings.API_V1_STR) app.add_exception_handler(StarletteHTTPException, exception_handler.http_exception_handler) app.add_exception_handler(Exception, exception_handler.global_exception_handler) -frontend_dist = os.path.abspath("../frontend/dist") -if not os.path.exists(frontend_dist): - logging.warning(f"The front-end build directory does not exist: {frontend_dist}") - logging.warning("Please make sure you have built the front-end project") -else: - - @app.get("/", include_in_schema=False) - async def read_index(): - return FileResponse(path=os.path.join(frontend_dist, "index.html")) - - - app.mount("/", StaticFiles(directory=frontend_dist), name="static") mcp.setup_server() diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 41aaea6a..8ed33305 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -35,10 +35,20 @@ dependencies = [ "oracledb (>=3.1.1,<4.0.0)", "pyyaml (>=6.0.2,<7.0.0)", "fastapi-mcp (>=0.3.4,<0.4.0)", + "sqlbot-xpack==0.0.2", ] [[tool.uv.index]] +name = "default" url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple" default = true +[[tool.uv.index]] + +name = "testpypi" +url = "https://test.pypi.org/simple" +explicit = true + +[tool.uv.sources] +sqlbot-xpack = { index = "testpypi" } [tool.uv] dev-dependencies = [ diff --git a/frontend/src/router/watch.ts b/frontend/src/router/watch.ts index 710d3c1d..98224f6b 100644 --- a/frontend/src/router/watch.ts +++ b/frontend/src/router/watch.ts @@ -1,12 +1,13 @@ import { ElMessage } from 'element-plus-secondary' import { useCache } from '@/utils/useCache' import { useUserStore } from '@/stores/user' - +import { request } from '@/utils/request' const userStore = useUserStore() const { wsCache } = useCache() const whiteList = ['/login'] export const watchRouter = (router: any) => { router.beforeEach(async (to: any, from: any, next: any) => { + await loadXpackStatic() const token = wsCache.get('user.token') if (whiteList.includes(to.path)) { next() @@ -32,3 +33,14 @@ export const watchRouter = (router: any) => { } }) } +const loadXpackStatic = () => { + if (document.getElementById('sqlbot_xpack_static')) { + return Promise.resolve() + } + const url = '/xpack_static/license-generator.umd.js' + return request.loadRemoteScript(url, 'sqlbot_xpack_static', () => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + LicenseGenerator?.init(import.meta.env.VITE_API_BASE_URL) + }) +} diff --git a/frontend/src/utils/request.ts b/frontend/src/utils/request.ts index 711d4f91..cf9e54b4 100644 --- a/frontend/src/utils/request.ts +++ b/frontend/src/utils/request.ts @@ -69,6 +69,15 @@ class HttpService { if (token && config.headers) { config.headers['X-SQLBOT-TOKEN'] = `Bearer ${token}` } + if (config.url?.includes('/xpack_static/') && config.baseURL) { + config.baseURL = config.baseURL.replace('/api/v1', '') + // Skip auth for xpack_static requests + return config + } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const request_key = LicenseGenerator.generate() + config.headers['X-SQLBOT-KEY'] = request_key // Request logging // console.log(`[Request] ${config.method?.toUpperCase()} ${config.url}`) @@ -258,6 +267,38 @@ class HttpService { responseType: 'blob', }) } + + public loadRemoteScript(url: string, id?: string, cb?: any): Promise { + if (!url) { + return Promise.reject(new Error('URL is required to load remote script')) + } + if (id && document.getElementById(id)) { + return Promise.resolve(document.getElementById(id) as HTMLElement) + } + return new Promise((resolve, reject) => { + this.get(url, { + responseType: 'text', + headers: { + 'Content-Type': 'application/javascript', + }, + }) + .then((response: any) => { + const script = document.createElement('script') + script.textContent = response + script.id = id || `remote-script-${Date.now()}` + // Append script to head + document.head.appendChild(script) + if (cb) { + cb() + } + resolve(script) + }) + .catch((error: any) => { + console.error(`Failed to load script from ${url}:`, error) + reject(new Error(`Failed to load script from ${url}: ${error.message}`)) + }) + }) + } } // Create singleton instance