[verified] refactor: establish service and frontend boundaries

This commit is contained in:
chick
2026-07-15 02:43:41 +08:00
parent 0ac6faa6a3
commit e04a16e817
29 changed files with 917 additions and 598 deletions
+27
View File
@@ -0,0 +1,27 @@
export function normalizeTargetUrl(raw) {
const url = new URL(raw)
if (!['http:', 'https:'].includes(url.protocol)) throw new Error('target URL must use http or https')
url.hash = ''; url.search = ''
return url.toString().replace(/\/$/, '')
}
export function createApiClient({ fetchImpl = globalThis.fetch } = {}) {
const request = async (url, options) => {
const response = await fetchImpl(url, options)
const data = await response.json().catch(() => ({}))
if (!response.ok) throw new Error(data.error || `HTTP ${response.status}`)
return data
}
return {
request,
config: () => request('/api/config'),
catalog: () => request('/api/catalog'),
status: () => request('/api/status'),
proxy: (id, endpoint, options) => fetchImpl(`/api/proxy/${encodeURIComponent(id)}${endpoint}`, options),
createInstance: payload => request('/api/instances', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(payload) }),
updateInstance: (id, payload) => request(`/api/instances/${encodeURIComponent(id)}`, { method: 'PUT', headers: { 'content-type': 'application/json' }, body: JSON.stringify(payload) }),
deleteInstance: id => request(`/api/instances/${encodeURIComponent(id)}`, { method: 'DELETE' }),
login: (id, password) => request(`/api/instances/${encodeURIComponent(id)}/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(password === undefined ? {} : { password }) }),
logout: id => request(`/api/instances/${encodeURIComponent(id)}/logout`, { method: 'POST' }),
}
}