|
|
|
@ -1196,98 +1196,6 @@ |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// API service - Updated to use xattrs for runtime configuration |
|
|
|
const API = { |
|
|
|
async request(url, options = {}) { |
|
|
|
try { |
|
|
|
const response = await fetch(url, { |
|
|
|
headers: { |
|
|
|
'Content-Type': 'application/json', |
|
|
|
...options.headers |
|
|
|
}, |
|
|
|
...options |
|
|
|
}); |
|
|
|
|
|
|
|
if (!response.ok) { |
|
|
|
const errorData = await response.json().catch(() => ({})); |
|
|
|
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`); |
|
|
|
} |
|
|
|
|
|
|
|
return await response.json(); |
|
|
|
} catch (error) { |
|
|
|
console.error('API request failed:', error); |
|
|
|
showToast(error.message || 'Request failed', 'error'); |
|
|
|
throw error; |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
async getMounts() { |
|
|
|
const data = await this.request('/mounts/mergerfs'); |
|
|
|
AppState.mounts = data; |
|
|
|
return data; |
|
|
|
}, |
|
|
|
|
|
|
|
async getAllMounts() { |
|
|
|
return await this.request('/mounts'); |
|
|
|
}, |
|
|
|
|
|
|
|
async getBranches(mount) { |
|
|
|
const response = await fetch(`/kvs/branches?mount=${encodeURIComponent(mount)}`); |
|
|
|
if (!response.ok) { |
|
|
|
const errorData = await response.json().catch(() => ({})); |
|
|
|
throw new Error(errorData.message || `HTTP ${response.status}: ${response.statusText}`); |
|
|
|
} |
|
|
|
return await response.text(); |
|
|
|
}, |
|
|
|
|
|
|
|
async getConfig(mount) { |
|
|
|
const data = await this.request(`/kvs?mount=${encodeURIComponent(mount)}`); |
|
|
|
return data; |
|
|
|
}, |
|
|
|
|
|
|
|
async setConfig(mount, key, value) { |
|
|
|
return await this.request(`/kvs/${encodeURIComponent(key)}?mount=${encodeURIComponent(mount)}`, { |
|
|
|
method: 'POST', |
|
|
|
body: JSON.stringify(value) |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
async setBranches(mount, branches) { |
|
|
|
return await this.request(`/kvs/branches?mount=${encodeURIComponent(mount)}`, { |
|
|
|
method: 'POST', |
|
|
|
body: JSON.stringify(branches) |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
// Runtime xattr operations |
|
|
|
async setXattr(mount, key, value) { |
|
|
|
// Use the .mergerfs pseudo file for runtime configuration |
|
|
|
const xattrKey = `user.mergerfs.${key}`; |
|
|
|
return await this.request(`/${encodeURIComponent(mount)}/.mergerfs`, { |
|
|
|
method: 'POST', |
|
|
|
headers: { |
|
|
|
'X-Attr-Key': xattrKey, |
|
|
|
'Content-Type': 'text/plain' |
|
|
|
}, |
|
|
|
body: value |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
async getXattr(mount, key) { |
|
|
|
const xattrKey = `user.mergerfs.${key}`; |
|
|
|
return await this.request(`/${encodeURIComponent(mount)}/.mergerfs?xattr=${encodeURIComponent(xattrKey)}`); |
|
|
|
}, |
|
|
|
|
|
|
|
async executeCommand(mount, command) { |
|
|
|
return await this.setXattr(mount, `cmd.${command}`, ''); |
|
|
|
}, |
|
|
|
|
|
|
|
async getFileInfo(mount, filePath, infoType) { |
|
|
|
const xattrKey = `user.mergerfs.${infoType}`; |
|
|
|
return await this.request(`/${encodeURIComponent(mount)}${filePath}?xattr=${encodeURIComponent(xattrKey)}`); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// UI Components |
|
|
|
const UI = { |
|
|
|
showLoading(element) { |
|
|
|
|