feat: add Docker support and update backend dependencies
- Introduced `requirements.docker.txt` for Docker-specific dependencies. - Updated `requirements.txt` to include `psycopg[binary]` and `python-multipart`. - Enhanced test suite in `test_main_endpoints.py` to cover document CRUD operations. - Modified `docker-compose.yml` to include PostgreSQL and frontend services. - Added Nginx configuration for reverse proxying API requests. - Refactored file handling in Vue components to support new document storage backend. - Created new utility functions in `docsApi.js` for document management. - Updated configuration to support new API endpoints for document operations. - Adjusted Vite configuration to proxy API requests to the local backend.
This commit is contained in:
+8
-3
@@ -1,6 +1,6 @@
|
||||
export const DEBUG = import.meta.env.DEV
|
||||
|
||||
const DEFAULT_API_BASE_URL = import.meta.env.DEV ? '' : 'https://api.imageteach.tech:8002'
|
||||
const DEFAULT_API_BASE_URL = ''
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || DEFAULT_API_BASE_URL
|
||||
|
||||
export const API_URL = import.meta.env.VITE_API_URL || `${API_BASE_URL}/v1/completions`
|
||||
@@ -15,8 +15,13 @@ export const TTS_CONFIG_URL = import.meta.env.VITE_TTS_CONFIG_URL || `${API_BASE
|
||||
export const ASR_URL = import.meta.env.VITE_ASR_URL || `${API_BASE_URL}/v1/tts-asr/asr`
|
||||
export const JOB_LOAD_URL = import.meta.env.VITE_JOB_LOAD_URL || `${API_BASE_URL}/v1/jobs/load`
|
||||
export const API_KEY = import.meta.env.VITE_API_KEY || 'your-secret-key-here'
|
||||
export const DOCS_NODES_URL = import.meta.env.VITE_DOCS_NODES_URL || `${API_BASE_URL}/v1/docs/nodes`
|
||||
export const DOCS_FOLDERS_URL = import.meta.env.VITE_DOCS_FOLDERS_URL || `${API_BASE_URL}/v1/docs/folders`
|
||||
export const DOCS_TEXT_FILES_URL = import.meta.env.VITE_DOCS_TEXT_FILES_URL || `${API_BASE_URL}/v1/docs/files/text`
|
||||
export const DOCS_UPLOAD_URL = import.meta.env.VITE_DOCS_UPLOAD_URL || `${API_BASE_URL}/v1/docs/files/upload`
|
||||
export const DOCS_BLOB_BASE_URL = import.meta.env.VITE_DOCS_BLOB_BASE_URL || `${API_BASE_URL}/v1/docs/files`
|
||||
export const DOCS_NODES_BASE_URL = import.meta.env.VITE_DOCS_NODES_BASE_URL || `${API_BASE_URL}/v1/docs/nodes`
|
||||
|
||||
// Compression always goes to local backend (not through reverse proxy)
|
||||
const COMPRESS_BASE_URL = import.meta.env.VITE_COMPRESS_BACKEND || 'http://localhost:8001'
|
||||
const COMPRESS_BASE_URL = import.meta.env.VITE_COMPRESS_BACKEND || API_BASE_URL
|
||||
export const COMPRESS_SUBMIT_URL = `${COMPRESS_BASE_URL}/v1/compress/submit`
|
||||
export const COMPRESS_STATUS_URL = `${COMPRESS_BASE_URL}/v1/compress/status`
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
import {
|
||||
API_KEY,
|
||||
DOCS_BLOB_BASE_URL,
|
||||
DOCS_FOLDERS_URL,
|
||||
DOCS_NODES_BASE_URL,
|
||||
DOCS_NODES_URL,
|
||||
DOCS_TEXT_FILES_URL,
|
||||
DOCS_UPLOAD_URL,
|
||||
} from './config.js'
|
||||
|
||||
function buildHeaders(extra = {}) {
|
||||
return {
|
||||
'X-API-Key': API_KEY,
|
||||
...extra,
|
||||
}
|
||||
}
|
||||
|
||||
async function parseJsonResponse(res) {
|
||||
if (!res.ok) {
|
||||
let message = `HTTP ${res.status}`
|
||||
try {
|
||||
const data = await res.json()
|
||||
message = data.detail || data.error || message
|
||||
} catch {
|
||||
const text = await res.text()
|
||||
if (text) message = text
|
||||
}
|
||||
throw new Error(message)
|
||||
}
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export async function fetchDocNodes() {
|
||||
const res = await fetch(DOCS_NODES_URL, {
|
||||
headers: buildHeaders(),
|
||||
})
|
||||
const data = await parseJsonResponse(res)
|
||||
return Array.isArray(data.nodes) ? data.nodes : []
|
||||
}
|
||||
|
||||
export async function createDocFolder(name, parentId = null) {
|
||||
const res = await fetch(DOCS_FOLDERS_URL, {
|
||||
method: 'POST',
|
||||
headers: buildHeaders({ 'Content-Type': 'application/json' }),
|
||||
body: JSON.stringify({ name, parentId }),
|
||||
})
|
||||
const data = await parseJsonResponse(res)
|
||||
return data.node
|
||||
}
|
||||
|
||||
export async function createDocTextFile(name, parentId = null, content = '') {
|
||||
const res = await fetch(DOCS_TEXT_FILES_URL, {
|
||||
method: 'POST',
|
||||
headers: buildHeaders({ 'Content-Type': 'application/json' }),
|
||||
body: JSON.stringify({ name, parentId, content }),
|
||||
})
|
||||
const data = await parseJsonResponse(res)
|
||||
return data.node
|
||||
}
|
||||
|
||||
export async function uploadDocFile(file, parentId = null) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
formData.append('parent_id', parentId || '')
|
||||
const res = await fetch(DOCS_UPLOAD_URL, {
|
||||
method: 'POST',
|
||||
headers: buildHeaders(),
|
||||
body: formData,
|
||||
})
|
||||
const data = await parseJsonResponse(res)
|
||||
return data.node
|
||||
}
|
||||
|
||||
export async function updateDocNode(nodeId, payload) {
|
||||
const res = await fetch(`${DOCS_NODES_BASE_URL}/${encodeURIComponent(nodeId)}`, {
|
||||
method: 'PATCH',
|
||||
headers: buildHeaders({ 'Content-Type': 'application/json' }),
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
const data = await parseJsonResponse(res)
|
||||
return data.node
|
||||
}
|
||||
|
||||
export async function replaceDocBlob(nodeId, file) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file, file.name || 'file')
|
||||
const res = await fetch(`${DOCS_BLOB_BASE_URL}/${encodeURIComponent(nodeId)}/blob`, {
|
||||
method: 'PUT',
|
||||
headers: buildHeaders(),
|
||||
body: formData,
|
||||
})
|
||||
const data = await parseJsonResponse(res)
|
||||
return data.node
|
||||
}
|
||||
|
||||
export async function deleteDocNode(nodeId) {
|
||||
const res = await fetch(`${DOCS_NODES_BASE_URL}/${encodeURIComponent(nodeId)}`, {
|
||||
method: 'DELETE',
|
||||
headers: buildHeaders(),
|
||||
})
|
||||
return parseJsonResponse(res)
|
||||
}
|
||||
|
||||
export async function fetchDocBlob(nodeId) {
|
||||
const res = await fetch(`${DOCS_BLOB_BASE_URL}/${encodeURIComponent(nodeId)}/blob`, {
|
||||
headers: buildHeaders(),
|
||||
})
|
||||
if (!res.ok) {
|
||||
let message = `HTTP ${res.status}`
|
||||
try {
|
||||
const data = await res.json()
|
||||
message = data.detail || data.error || message
|
||||
} catch {
|
||||
const text = await res.text()
|
||||
if (text) message = text
|
||||
}
|
||||
throw new Error(message)
|
||||
}
|
||||
return res.blob()
|
||||
}
|
||||
Reference in New Issue
Block a user