mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-28 16:32:28 +00:00
156 lines
4.2 KiB
JavaScript
156 lines
4.2 KiB
JavaScript
import { userLogger } from "../utils/logger.js";
|
|
import { normalizeS3PublicBaseUrl } from "./s3-url.js";
|
|
|
|
const DB_NAME = "bitvidSettings";
|
|
const DB_VERSION = 1;
|
|
const STORE_NAME = "kv";
|
|
const SETTINGS_KEY = "s3Settings";
|
|
const LOCALSTORAGE_FALLBACK_KEY = "bitvid:s3Settings";
|
|
|
|
function normalizeSettings(raw) {
|
|
const base = raw && typeof raw === "object" ? raw : {};
|
|
const forcePathStyle = Boolean(base.forcePathStyle);
|
|
const createBucketIfMissing = Boolean(base.createBucketIfMissing);
|
|
const endpoint = String(base.endpoint || "").trim();
|
|
const region = String(base.region || "").trim() || "auto";
|
|
const bucket = String(base.bucket || "").trim();
|
|
const accessKeyId = String(base.accessKeyId || "").trim();
|
|
const secretAccessKey = String(base.secretAccessKey || "").trim();
|
|
const publicBaseUrl = normalizeS3PublicBaseUrl(base.publicBaseUrl || "");
|
|
|
|
return {
|
|
endpoint,
|
|
region,
|
|
bucket,
|
|
accessKeyId,
|
|
secretAccessKey,
|
|
forcePathStyle,
|
|
publicBaseUrl,
|
|
createBucketIfMissing,
|
|
};
|
|
}
|
|
|
|
function isIndexedDbAvailable() {
|
|
try {
|
|
return typeof indexedDB !== "undefined";
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function openSettingsDb() {
|
|
return new Promise((resolve, reject) => {
|
|
if (!isIndexedDbAvailable()) {
|
|
resolve(null);
|
|
return;
|
|
}
|
|
|
|
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
|
|
request.onupgradeneeded = () => {
|
|
const db = request.result;
|
|
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
db.createObjectStore(STORE_NAME);
|
|
}
|
|
};
|
|
|
|
request.onsuccess = () => {
|
|
resolve(request.result);
|
|
};
|
|
|
|
request.onerror = () => {
|
|
reject(request.error || new Error("Failed to open settings DB"));
|
|
};
|
|
});
|
|
}
|
|
|
|
export async function loadS3Settings() {
|
|
try {
|
|
const db = await openSettingsDb();
|
|
if (db) {
|
|
return await new Promise((resolve, reject) => {
|
|
const tx = db.transaction(STORE_NAME, "readonly");
|
|
const store = tx.objectStore(STORE_NAME);
|
|
const req = store.get(SETTINGS_KEY);
|
|
req.onsuccess = () => {
|
|
resolve(normalizeSettings(req.result));
|
|
};
|
|
req.onerror = () => {
|
|
reject(req.error || new Error("Failed to load S3 settings"));
|
|
};
|
|
});
|
|
}
|
|
} catch (err) {
|
|
userLogger.warn("Failed to open IndexedDB for S3 settings, falling back:", err);
|
|
}
|
|
|
|
try {
|
|
if (typeof localStorage !== "undefined") {
|
|
const raw = localStorage.getItem(LOCALSTORAGE_FALLBACK_KEY);
|
|
if (raw) {
|
|
return normalizeSettings(JSON.parse(raw));
|
|
}
|
|
}
|
|
} catch (err) {
|
|
userLogger.warn("Failed to read fallback S3 settings:", err);
|
|
}
|
|
|
|
return normalizeSettings(null);
|
|
}
|
|
|
|
export async function saveS3Settings(settings) {
|
|
const normalized = normalizeSettings(settings);
|
|
|
|
let db = null;
|
|
try {
|
|
db = await openSettingsDb();
|
|
} catch (err) {
|
|
userLogger.warn("Unable to open IndexedDB for S3 settings, continuing with fallback:", err);
|
|
}
|
|
|
|
if (db) {
|
|
await new Promise((resolve, reject) => {
|
|
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
const store = tx.objectStore(STORE_NAME);
|
|
const req = store.put(normalized, SETTINGS_KEY);
|
|
req.onsuccess = () => resolve();
|
|
req.onerror = () =>
|
|
reject(req.error || new Error("Failed to save S3 settings"));
|
|
});
|
|
} else if (typeof localStorage !== "undefined") {
|
|
localStorage.setItem(LOCALSTORAGE_FALLBACK_KEY, JSON.stringify(normalized));
|
|
}
|
|
|
|
return normalized;
|
|
}
|
|
|
|
export async function clearS3Settings() {
|
|
let cleared = false;
|
|
try {
|
|
const db = await openSettingsDb();
|
|
if (db) {
|
|
await new Promise((resolve, reject) => {
|
|
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
const store = tx.objectStore(STORE_NAME);
|
|
const req = store.delete(SETTINGS_KEY);
|
|
req.onsuccess = () => resolve();
|
|
req.onerror = () => reject(req.error || new Error("Failed to clear"));
|
|
});
|
|
cleared = true;
|
|
}
|
|
} catch (err) {
|
|
userLogger.warn("Failed to clear IndexedDB S3 settings:", err);
|
|
}
|
|
|
|
try {
|
|
if (typeof localStorage !== "undefined") {
|
|
localStorage.removeItem(LOCALSTORAGE_FALLBACK_KEY);
|
|
cleared = true;
|
|
}
|
|
} catch (err) {
|
|
userLogger.warn("Failed to clear fallback S3 settings:", err);
|
|
}
|
|
|
|
return cleared;
|
|
}
|