updated the API to support the new calendar service and added a smoke test for the API.
This commit is contained in:
+18
-11
@@ -1,7 +1,6 @@
|
|||||||
(function () {
|
(function () {
|
||||||
const apiBaseUrlStorageKey = "tarot-time-api-base-url";
|
const apiBaseUrlStorageKey = "tarot-time-api-base-url";
|
||||||
const apiKeyStorageKey = "tarot-time-api-key";
|
const apiKeyStorageKey = "tarot-time-api-key";
|
||||||
const defaultApiBaseUrl = "";
|
|
||||||
|
|
||||||
function normalizeBaseUrl(value) {
|
function normalizeBaseUrl(value) {
|
||||||
return String(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) {
|
function persistConnectionSettings(settings) {
|
||||||
let didPersist = true;
|
let didPersist = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const params = new URLSearchParams(window.location.search || "");
|
const params = new URLSearchParams(window.location.search || "");
|
||||||
const queryValue = String(params.get("apiBaseUrl") || "").trim();
|
const queryValue = String(params.get("apiBaseUrl") || "").trim();
|
||||||
const queryApiKey = String(params.get("apiKey") || params.get("api_key") || "").trim();
|
|
||||||
|
|
||||||
if (queryValue) {
|
if (queryValue) {
|
||||||
window.localStorage.setItem(apiBaseUrlStorageKey, normalizeBaseUrl(queryValue));
|
window.localStorage.setItem(apiBaseUrlStorageKey, normalizeBaseUrl(queryValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryApiKey) {
|
|
||||||
window.localStorage.setItem(apiKeyStorageKey, normalizeApiKey(queryApiKey));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.apiBaseUrl) {
|
if (settings.apiBaseUrl) {
|
||||||
window.localStorage.setItem(apiBaseUrlStorageKey, settings.apiBaseUrl);
|
window.localStorage.setItem(apiBaseUrlStorageKey, settings.apiBaseUrl);
|
||||||
} else {
|
} else {
|
||||||
@@ -58,16 +68,11 @@
|
|||||||
try {
|
try {
|
||||||
const params = new URLSearchParams(window.location.search || "");
|
const params = new URLSearchParams(window.location.search || "");
|
||||||
const queryValue = String(params.get("apiBaseUrl") || "").trim();
|
const queryValue = String(params.get("apiBaseUrl") || "").trim();
|
||||||
const queryApiKey = String(params.get("apiKey") || params.get("api_key") || "").trim();
|
|
||||||
|
|
||||||
if (queryValue) {
|
if (queryValue) {
|
||||||
window.localStorage.setItem(apiBaseUrlStorageKey, normalizeBaseUrl(queryValue));
|
window.localStorage.setItem(apiBaseUrlStorageKey, normalizeBaseUrl(queryValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryApiKey) {
|
|
||||||
window.localStorage.setItem(apiKeyStorageKey, normalizeApiKey(queryApiKey));
|
|
||||||
}
|
|
||||||
|
|
||||||
const storedBaseUrl = String(window.localStorage.getItem(apiBaseUrlStorageKey) || "").trim();
|
const storedBaseUrl = String(window.localStorage.getItem(apiBaseUrlStorageKey) || "").trim();
|
||||||
const storedApiKey = String(window.localStorage.getItem(apiKeyStorageKey) || "").trim();
|
const storedApiKey = String(window.localStorage.getItem(apiKeyStorageKey) || "").trim();
|
||||||
return normalizeConnectionSettings({
|
return normalizeConnectionSettings({
|
||||||
@@ -82,6 +87,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stripLegacyCredentialParams();
|
||||||
|
|
||||||
const initialConnectionSettings = readConfiguredConnectionSettings();
|
const initialConnectionSettings = readConfiguredConnectionSettings();
|
||||||
|
|
||||||
window.TarotAppConfig = {
|
window.TarotAppConfig = {
|
||||||
|
|||||||
+1
-12
@@ -192,11 +192,6 @@
|
|||||||
url.searchParams.set(key, normalizedValue);
|
url.searchParams.set(key, normalizedValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
const apiKey = getApiKey();
|
|
||||||
if (apiKey && !url.searchParams.has("api_key")) {
|
|
||||||
url.searchParams.set("api_key", apiKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return url.toString();
|
return url.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,13 +206,7 @@
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = new URL(`/api/v1/assets/${encodePathSegments(normalizedAssetPath)}`, `${apiBaseUrl}/`);
|
return new URL(`/api/v1/assets/${encodePathSegments(normalizedAssetPath)}`, `${apiBaseUrl}/`).toString();
|
||||||
const apiKey = getApiKey();
|
|
||||||
if (apiKey) {
|
|
||||||
url.searchParams.set("api_key", apiKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return url.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetCaches() {
|
function resetCaches() {
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
"@tootallnate/once": "3.0.1"
|
"@tootallnate/once": "3.0.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"check": "npm run check:syntax",
|
||||||
|
"check:syntax": "node scripts/check-syntax.js app.js app scripts",
|
||||||
"start": "npx http-server . -o index.html",
|
"start": "npx http-server . -o index.html",
|
||||||
"dev": "npm run start"
|
"dev": "npm run start"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
Reference in New Issue
Block a user