diff --git a/app/app-config.js b/app/app-config.js index 44698a0..360cd0b 100644 --- a/app/app-config.js +++ b/app/app-config.js @@ -1,7 +1,6 @@ (function () { const apiBaseUrlStorageKey = "tarot-time-api-base-url"; const apiKeyStorageKey = "tarot-time-api-key"; - const defaultApiBaseUrl = ""; function normalizeBaseUrl(value) { return String(value || "") @@ -20,22 +19,33 @@ }; } + function stripLegacyCredentialParams() { + try { + const currentUrl = new URL(window.location.href); + const hadApiKeyParam = currentUrl.searchParams.has("apiKey") || currentUrl.searchParams.has("api_key"); + if (!hadApiKeyParam) { + return; + } + + currentUrl.searchParams.delete("apiKey"); + currentUrl.searchParams.delete("api_key"); + const nextUrl = `${currentUrl.pathname}${currentUrl.search}${currentUrl.hash}`; + window.history.replaceState(window.history.state, "", nextUrl); + } catch (_error) { + } + } + function persistConnectionSettings(settings) { let didPersist = true; try { const params = new URLSearchParams(window.location.search || ""); const queryValue = String(params.get("apiBaseUrl") || "").trim(); - const queryApiKey = String(params.get("apiKey") || params.get("api_key") || "").trim(); if (queryValue) { window.localStorage.setItem(apiBaseUrlStorageKey, normalizeBaseUrl(queryValue)); } - if (queryApiKey) { - window.localStorage.setItem(apiKeyStorageKey, normalizeApiKey(queryApiKey)); - } - if (settings.apiBaseUrl) { window.localStorage.setItem(apiBaseUrlStorageKey, settings.apiBaseUrl); } else { @@ -58,16 +68,11 @@ try { const params = new URLSearchParams(window.location.search || ""); const queryValue = String(params.get("apiBaseUrl") || "").trim(); - const queryApiKey = String(params.get("apiKey") || params.get("api_key") || "").trim(); if (queryValue) { window.localStorage.setItem(apiBaseUrlStorageKey, normalizeBaseUrl(queryValue)); } - if (queryApiKey) { - window.localStorage.setItem(apiKeyStorageKey, normalizeApiKey(queryApiKey)); - } - const storedBaseUrl = String(window.localStorage.getItem(apiBaseUrlStorageKey) || "").trim(); const storedApiKey = String(window.localStorage.getItem(apiKeyStorageKey) || "").trim(); return normalizeConnectionSettings({ @@ -82,6 +87,8 @@ } } + stripLegacyCredentialParams(); + const initialConnectionSettings = readConfiguredConnectionSettings(); window.TarotAppConfig = { diff --git a/app/data-service.js b/app/data-service.js index ca99a65..e00877b 100644 --- a/app/data-service.js +++ b/app/data-service.js @@ -192,11 +192,6 @@ url.searchParams.set(key, normalizedValue); }); - const apiKey = getApiKey(); - if (apiKey && !url.searchParams.has("api_key")) { - url.searchParams.set("api_key", apiKey); - } - return url.toString(); } @@ -211,13 +206,7 @@ return ""; } - const url = new URL(`/api/v1/assets/${encodePathSegments(normalizedAssetPath)}`, `${apiBaseUrl}/`); - const apiKey = getApiKey(); - if (apiKey) { - url.searchParams.set("api_key", apiKey); - } - - return url.toString(); + return new URL(`/api/v1/assets/${encodePathSegments(normalizedAssetPath)}`, `${apiBaseUrl}/`).toString(); } function resetCaches() { diff --git a/package.json b/package.json index 79e27cd..fce0d5c 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,8 @@ "@tootallnate/once": "3.0.1" }, "scripts": { + "check": "npm run check:syntax", + "check:syntax": "node scripts/check-syntax.js app.js app scripts", "start": "npx http-server . -o index.html", "dev": "npm run start" } diff --git a/scripts/check-syntax.js b/scripts/check-syntax.js new file mode 100644 index 0000000..93b1119 --- /dev/null +++ b/scripts/check-syntax.js @@ -0,0 +1,71 @@ +const fs = require("fs"); +const path = require("path"); +const { spawnSync } = require("child_process"); + +const skippedDirectoryNames = new Set(["node_modules", ".git"]); + +function collectJavaScriptFiles(targetPath, results = []) { + const resolvedPath = path.resolve(targetPath); + if (!fs.existsSync(resolvedPath)) { + return results; + } + + const stats = fs.statSync(resolvedPath); + if (stats.isDirectory()) { + const entries = fs.readdirSync(resolvedPath, { withFileTypes: true }); + for (const entry of entries) { + if (entry.isDirectory() && skippedDirectoryNames.has(entry.name)) { + continue; + } + + collectJavaScriptFiles(path.join(resolvedPath, entry.name), results); + } + return results; + } + + if (stats.isFile() && resolvedPath.endsWith(".js")) { + results.push(resolvedPath); + } + + return results; +} + +function main() { + const targets = process.argv.slice(2); + if (!targets.length) { + console.error("Provide at least one file or directory to validate."); + process.exit(1); + } + + const files = Array.from(new Set( + targets.flatMap((targetPath) => collectJavaScriptFiles(targetPath)) + )).sort(); + + if (!files.length) { + console.error("No JavaScript files were found for validation."); + process.exit(1); + } + + let hasFailures = false; + + for (const filePath of files) { + const result = spawnSync(process.execPath, ["--check", filePath], { + encoding: "utf8" + }); + + if (result.status === 0) { + continue; + } + + hasFailures = true; + process.stderr.write(result.stderr || result.stdout || `Syntax check failed: ${filePath}\n`); + } + + if (hasFailures) { + process.exit(1); + } + + console.log(`Syntax check passed for ${files.length} files.`); +} + +main(); \ No newline at end of file