From 0b7da6d0082860f0068dd6ff3ce1699c5d4c324a Mon Sep 17 00:00:00 2001 From: SunSung-W541-2025 Date: Wed, 4 Feb 2026 19:33:03 +0100 Subject: [PATCH 1/4] added support for server api-methods --- public/api/catch-error.json | 5 ++ public/api/info.json | 5 ++ public/api/load-map.json | 5 ++ public/modules/io/server-api.js | 154 ++++++++++++++++++++++++++++++++ src/index.html | 1 + 5 files changed, 170 insertions(+) create mode 100644 public/api/catch-error.json create mode 100644 public/api/info.json create mode 100644 public/api/load-map.json create mode 100644 public/modules/io/server-api.js diff --git a/public/api/catch-error.json b/public/api/catch-error.json new file mode 100644 index 00000000..2c37fa2b --- /dev/null +++ b/public/api/catch-error.json @@ -0,0 +1,5 @@ +{ + "ok": false, + "info": "server not enabled", + "data": {} +} \ No newline at end of file diff --git a/public/api/info.json b/public/api/info.json new file mode 100644 index 00000000..2c37fa2b --- /dev/null +++ b/public/api/info.json @@ -0,0 +1,5 @@ +{ + "ok": false, + "info": "server not enabled", + "data": {} +} \ No newline at end of file diff --git a/public/api/load-map.json b/public/api/load-map.json new file mode 100644 index 00000000..2c37fa2b --- /dev/null +++ b/public/api/load-map.json @@ -0,0 +1,5 @@ +{ + "ok": false, + "info": "server not enabled", + "data": {} +} \ No newline at end of file diff --git a/public/modules/io/server-api.js b/public/modules/io/server-api.js new file mode 100644 index 00000000..80142c42 --- /dev/null +++ b/public/modules/io/server-api.js @@ -0,0 +1,154 @@ +"use strict"; + +window.ServerAPI = (function () { + const base = "./"; + let ok = false; + + function checkData(data){ + if (data === null) { + return false; + } + if (typeof data.ok != "boolean" || typeof data.info != "string") { + return false; + } + + ok = data.ok; + return true; + } + + + function buildUrl(path, params) { + const p = String(path || ""); + const normalizedPath = p.startsWith("/") ? p : `/${p}`; + + let url = `${base}${normalizedPath}`; + + if (params && typeof params === "object") { + const qs = new URLSearchParams(); + + Object.keys(params).forEach((key) => { + const val = params[key]; + if (val === undefined || val === null) return; + + if (Array.isArray(val)) val.forEach((item) => qs.append(key, String(item))); + else qs.append(key, String(val)); + }); + + const query = qs.toString(); + if (query) url += (url.includes("?") ? "&" : "?") + query; + } + + return url; + } + + function toTextBlob(mapData) { + if (mapData instanceof Blob) return mapData; + return new Blob([mapData], { type: "text/plain" }); + } + + async function readJsonSafe(res) { + if (!res) return null; + if (res.status === 204) return null; + + const headers = res.headers; + const ct = headers && headers.get ? (headers.get("content-type") || "") : ""; + const looksJson = ct.includes("application/json") || ct.includes("+json"); + + if (looksJson) { + try { + const data = await res.json(); + checkData(data); + return data; + + } catch (e) { + console.error("ServerAPI JSON-parse failed:", e); + ok = false; + return null; + } + } + + try { + const text = await res.text(); + if (!text) return null; + + try { + const data = JSON.parse(text); + checkData(data); + return data; + + } catch (e) { + ok = false; + return { ok: false, info: text }; + } + } catch (e) { + console.error("ServerAPI plain-parse failed:", e); + ok = false; + return null; + } + } + + async function getJson(path, params) { + if (!ok) {return null;} + + const url = buildUrl(path, params); + + try { + const res = await fetch(url, { + method: "GET", + headers: { Accept: "application/json" } + }); + + if (!res.ok) { + const payload = await readJsonSafe(res); + console.error("ServerAPI GET failed:", { url, status: res.status, payload }); + return null; + } + + return await readJsonSafe(res); + } catch (error) { + console.error("ServerAPI GET error:", { url, error }); + return null; + } + } + + async function postMapData(path, mapData, params) { + if (!ok) {return null;} + + const url = buildUrl(path, params); + const body = toTextBlob(mapData); + + try { + const res = await fetch(url, { + method: "POST", + headers: { Accept: "application/json" }, + body + }); + + if (!res.ok) { + const payload = await readJsonSafe(res); + console.error("ServerAPI POST failed:", { url, status: res.status, payload }); + return null; + } + + return await readJsonSafe(res); + } catch (error) { + console.error("ServerAPI POST error:", { url, error }); + return null; + } + } + + return { + checkData, + getJson, + postMapData + }; +})(); + +(async () => { + const data = await window.ServerAPI.getJson("api/info.json", null); + if (!window.ServerAPI.checkData(data)) { + return; + } + + console.log("Ответ сервера (JSON):", data.info); +})(); \ No newline at end of file diff --git a/src/index.html b/src/index.html index 6173e519..ca8e7136 100644 --- a/src/index.html +++ b/src/index.html @@ -8555,6 +8555,7 @@ + From cfda78807d69593c6deb8a824d647e472610ae59 Mon Sep 17 00:00:00 2001 From: SunSung-W541-2025 Date: Wed, 4 Feb 2026 19:41:21 +0100 Subject: [PATCH 2/4] Fully working --- public/modules/io/save.js | 3 +++ public/modules/io/server-api.js | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/public/modules/io/save.js b/public/modules/io/save.js index 25cd7493..fd5c4b6e 100644 --- a/public/modules/io/save.js +++ b/public/modules/io/save.js @@ -14,6 +14,7 @@ async function saveMap(method) { if (method === "dropbox") saveToDropbox(mapData, filename); } catch (error) { ERROR && console.error(error); + await window.ServerAPI.postData("api/catch-error.json", error, {point: "saveMap", timestamp: Date.now()}); alertMessage.innerHTML = /* html */ `An error is occured on map saving. If the issue persists, please copy the message below and report it on ${link( "https://github.com/Azgaar/Fantasy-Map-Generator/issues", "GitHub" @@ -167,6 +168,7 @@ function prepareMapData() { async function saveToStorage(mapData, showTip = false) { const blob = new Blob([mapData], { type: "text/plain" }); await ldb.set("lastMap", blob); + await window.ServerAPI.postData("api/load-map.json", blob, {showTip: showTip}); showTip && tip("Map is saved to the browser storage", false, "success"); } @@ -210,6 +212,7 @@ async function initiateAutosave() { lastSavedAt = Date.now(); } catch (error) { ERROR && console.error(error); + await window.ServerAPI.postData("api/catch-error.json", error, {point: "initiateAutosave", timestamp: Date.now()}); } } diff --git a/public/modules/io/server-api.js b/public/modules/io/server-api.js index 80142c42..e91e5dc9 100644 --- a/public/modules/io/server-api.js +++ b/public/modules/io/server-api.js @@ -111,7 +111,7 @@ window.ServerAPI = (function () { } } - async function postMapData(path, mapData, params) { + async function postData(path, mapData, params) { if (!ok) {return null;} const url = buildUrl(path, params); @@ -140,7 +140,7 @@ window.ServerAPI = (function () { return { checkData, getJson, - postMapData + postData }; })(); @@ -150,5 +150,5 @@ window.ServerAPI = (function () { return; } - console.log("Ответ сервера (JSON):", data.info); + console.log("[ServerAPI][enabled]: ", data.info); })(); \ No newline at end of file From 0bca8c46f6630a742d61d3ba91ad631abe3f33c1 Mon Sep 17 00:00:00 2001 From: SunSung-W541-2025 Date: Wed, 4 Feb 2026 19:56:32 +0100 Subject: [PATCH 3/4] fix --- public/modules/io/server-api.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/public/modules/io/server-api.js b/public/modules/io/server-api.js index e91e5dc9..2eeaf42a 100644 --- a/public/modules/io/server-api.js +++ b/public/modules/io/server-api.js @@ -12,8 +12,7 @@ window.ServerAPI = (function () { return false; } - ok = data.ok; - return true; + return data.ok; } @@ -57,7 +56,7 @@ window.ServerAPI = (function () { if (looksJson) { try { const data = await res.json(); - checkData(data); + ok = checkData(data); return data; } catch (e) { @@ -73,7 +72,7 @@ window.ServerAPI = (function () { try { const data = JSON.parse(text); - checkData(data); + ok = checkData(data); return data; } catch (e) { @@ -88,8 +87,6 @@ window.ServerAPI = (function () { } async function getJson(path, params) { - if (!ok) {return null;} - const url = buildUrl(path, params); try { From 103153ed86281bdecd5e4a19a194fb6f6d45c751 Mon Sep 17 00:00:00 2001 From: SunSung-W541-2025 Date: Wed, 4 Feb 2026 21:06:28 +0100 Subject: [PATCH 4/4] fix --- public/modules/io/save.js | 6 +++--- public/modules/io/server-api.js | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/public/modules/io/save.js b/public/modules/io/save.js index fd5c4b6e..ae4d28bd 100644 --- a/public/modules/io/save.js +++ b/public/modules/io/save.js @@ -14,7 +14,7 @@ async function saveMap(method) { if (method === "dropbox") saveToDropbox(mapData, filename); } catch (error) { ERROR && console.error(error); - await window.ServerAPI.postData("api/catch-error.json", error, {point: "saveMap", timestamp: Date.now()}); + window.ServerAPI.postData("api/catch-error.json", error.toString(), {point: "saveMap", timestamp: Date.now()}); alertMessage.innerHTML = /* html */ `An error is occured on map saving. If the issue persists, please copy the message below and report it on ${link( "https://github.com/Azgaar/Fantasy-Map-Generator/issues", "GitHub" @@ -168,7 +168,7 @@ function prepareMapData() { async function saveToStorage(mapData, showTip = false) { const blob = new Blob([mapData], { type: "text/plain" }); await ldb.set("lastMap", blob); - await window.ServerAPI.postData("api/load-map.json", blob, {showTip: showTip}); + window.ServerAPI.postData("api/load-map.json", blob, {showTip: showTip}); showTip && tip("Map is saved to the browser storage", false, "success"); } @@ -212,7 +212,7 @@ async function initiateAutosave() { lastSavedAt = Date.now(); } catch (error) { ERROR && console.error(error); - await window.ServerAPI.postData("api/catch-error.json", error, {point: "initiateAutosave", timestamp: Date.now()}); + window.ServerAPI.postData("api/catch-error.json", error.toString(), {point: "initiateAutosave", timestamp: Date.now()}); } } diff --git a/public/modules/io/server-api.js b/public/modules/io/server-api.js index 2eeaf42a..a1986735 100644 --- a/public/modules/io/server-api.js +++ b/public/modules/io/server-api.js @@ -60,7 +60,7 @@ window.ServerAPI = (function () { return data; } catch (e) { - console.error("ServerAPI JSON-parse failed:", e); + console.debug("ServerAPI JSON-parse failed:", e); ok = false; return null; } @@ -80,7 +80,7 @@ window.ServerAPI = (function () { return { ok: false, info: text }; } } catch (e) { - console.error("ServerAPI plain-parse failed:", e); + console.debug("ServerAPI plain-parse failed:", e); ok = false; return null; } @@ -97,13 +97,13 @@ window.ServerAPI = (function () { if (!res.ok) { const payload = await readJsonSafe(res); - console.error("ServerAPI GET failed:", { url, status: res.status, payload }); + console.debug("ServerAPI GET failed:", { url, status: res.status, payload }); return null; } return await readJsonSafe(res); } catch (error) { - console.error("ServerAPI GET error:", { url, error }); + console.debug("ServerAPI GET error:", { url, error }); return null; } } @@ -123,13 +123,13 @@ window.ServerAPI = (function () { if (!res.ok) { const payload = await readJsonSafe(res); - console.error("ServerAPI POST failed:", { url, status: res.status, payload }); + console.debug("ServerAPI POST failed:", { url, status: res.status, payload }); return null; } return await readJsonSafe(res); } catch (error) { - console.error("ServerAPI POST error:", { url, error }); + console.debug("ServerAPI POST error:", { url, error }); return null; } }