// // Preference access. Every key may be overridden per-workspace; workspace // values win when they are actually set, otherwise the global value applies. // const DEFAULTS = { "gitea.baseUrl": "https://gitea.com", "gitea.discovery.mode": "workspace", "gitea.refresh.runningIntervalSeconds": 15, "gitea.refresh.idleIntervalSeconds": 60, "gitea.maxRunsPerRepo": 20, "gitea.maxJobsPerRun": 50, "gitea.reviewComments.enabled": true, "gitea.jobLogs.saveToRepo": true, "gitea.artifacts.downloadPath": ".tmp/gitea-artifacts/", "gitea.notifications.failedRuns": true, "gitea.branchFilter": "current", }; function isUnset(value) { return value === null || value === undefined || value === ""; } function get(key, type) { let value = null; if (nova.workspace && nova.workspace.config) { value = nova.workspace.config.get(key, type); } if (isUnset(value)) { value = nova.config.get(key, type); } if (isUnset(value)) { value = DEFAULTS[key]; } return isUnset(value) ? null : value; } function num(key) { const value = Number(get(key, "number")); return Number.isFinite(value) ? value : DEFAULTS[key]; } function bool(key) { const value = get(key, "boolean"); return value === null ? DEFAULTS[key] === true : value === true; } /** Trailing slashes make every later URL join ambiguous, so strip them once here. */ function normalizeBaseUrl(url) { if (!url) return null; let trimmed = String(url).trim().replace(/\/+$/, ""); if (!trimmed) return null; if (!/^https?:\/\//i.test(trimmed)) trimmed = "https://" + trimmed; return trimmed; } /** The default instance plus any extras, de-duplicated and order-preserving. */ function instances() { const list = []; const seen = new Set(); const add = (url) => { const normalized = normalizeBaseUrl(url); if (normalized && !seen.has(normalized)) { seen.add(normalized); list.push(normalized); } }; add(get("gitea.baseUrl", "string")); const extra = nova.config.get("gitea.instances", "array") || (nova.workspace && nova.workspace.config.get("gitea.instances", "array")) || []; for (const url of extra) add(url); return list; } function setInstances(list) { const cleaned = []; const primary = normalizeBaseUrl(get("gitea.baseUrl", "string")); for (const url of list) { const normalized = normalizeBaseUrl(url); if (normalized && normalized !== primary && !cleaned.includes(normalized)) { cleaned.push(normalized); } } nova.config.set("gitea.instances", cleaned); } function branchFilter() { const custom = get("gitea.branchFilter.custom", "string"); if (!isUnset(custom)) return { mode: "custom", branch: String(custom).trim() }; const mode = get("gitea.branchFilter", "string"); return { mode: mode === "all" ? "all" : "current", branch: null }; } function setBranchFilter(mode, branch) { const scope = nova.workspace && nova.workspace.path ? nova.workspace.config : nova.config; if (mode === "custom") { scope.set("gitea.branchFilter", "current"); scope.set("gitea.branchFilter.custom", branch); } else { scope.set("gitea.branchFilter", mode); scope.remove("gitea.branchFilter.custom"); } } exports.get = get; exports.num = num; exports.bool = bool; exports.instances = instances; exports.setInstances = setInstances; exports.normalizeBaseUrl = normalizeBaseUrl; exports.branchFilter = branchFilter; exports.setBranchFilter = setBranchFilter; exports.discoveryMode = () => get("gitea.discovery.mode", "string") || "workspace"; exports.maxRuns = () => num("gitea.maxRunsPerRepo"); exports.maxJobs = () => num("gitea.maxJobsPerRun"); exports.runningInterval = () => num("gitea.refresh.runningIntervalSeconds"); exports.idleInterval = () => num("gitea.refresh.idleIntervalSeconds"); exports.reviewCommentsEnabled = () => bool("gitea.reviewComments.enabled"); exports.saveLogsToRepo = () => bool("gitea.jobLogs.saveToRepo"); exports.notifyFailedRuns = () => bool("gitea.notifications.failedRuns"); exports.artifactDownloadPath = () => get("gitea.artifacts.downloadPath", "string") || ".tmp/gitea-artifacts/";