1 import { untrack } from 'svelte';
2 import { generate_nominatim_api_url } from '../lib/api_utils.js';
3 import { identifyLinkInQuery } from '../lib/helpers.js';
5 const default_pagename = Nominatim_Config.Reverse_Only ? 'reverse' : 'search';
19 lastApiRequestURL = $state(null);
20 errorMessage = $state(null);
21 requestProgress = $state('finish');
29 refreshPage(pagename, params) {
30 if (typeof pagename === 'undefined') {
31 pagename = window.location.pathname.replace('.html', '').replace(/^.*\//, '');
33 if (!pagenames.includes(pagename)) pagename = default_pagename;
35 params = new URLSearchParams(window.location.search);
37 if (!pagenames.includes(pagename)) pagename = default_pagename;
39 if (typeof params === 'undefined') {
40 params = new URLSearchParams();
43 let param_str = params.toString();
45 param_str = '?' + param_str;
47 let new_url = pagename + '.html' + param_str;
49 if (window.location.protocol.match(/^http/)) {
50 window.history.pushState([], '', new_url);
52 window.location.href = new_url;
56 if (pagename === 'search' && params.has('q')) {
57 const arrTypeAndId = identifyLinkInQuery(params.get('q'));
58 if (arrTypeAndId instanceof Array) {
60 params = new URLSearchParams({osmtype: arrTypeAndId[0], osmid: arrTypeAndId[1]});
65 if (this.page?.tab !== pagename && this.#abortController) {
66 this.#abortController.abort();
67 this.#abortController = undefined;
69 this.page = { tab: pagename, params: params };
70 this.lastApiRequestURL = null;
71 this.errorMessage = null;
75 async fetchFromApi(endpoint_name, params, callback) {
76 const api_url = generate_nominatim_api_url(endpoint_name, params);
78 const mock_api_error = (new URLSearchParams(window.location.search)).get('mock_api_error');
80 const fetchOptions = {};
82 this.requestProgress = 'start';
83 if (endpoint_name !== 'status') {
84 this.lastApiRequestURL = null;
85 // avoid API requests running in parallel
86 this.#abortController?.abort();
87 this.#abortController = new AbortController();
88 fetchOptions.signal = this.#abortController.signal;
91 if (Nominatim_Config.Nominatim_API_Endpoint_Headers) {
92 fetchOptions.headers = Nominatim_Config.Nominatim_API_Endpoint_Headers;
96 await fetch(api_url, fetchOptions)
97 .then(async (response) => {
98 if ((!((response.status >= 200 && response.status < 300) || response.status === 404))
99 || mock_api_error === 'fetch'
101 this.errorMessage = `Error fetching data from ${api_url} (${response.statusText})`;
105 // Parse JSON here instead of returning a promise so we can catch possible
109 if (mock_api_error === 'parse') {
110 data = JSON.parse('{');
112 data = await response.json();
115 // e.g. 'JSON.parse: unexpected non-whitespace character after JSON data at line 1'
116 this.errorMessage = `Error parsing JSON data from ${api_url} (${err})`;
124 this.errorMessage = data.error.message;
128 this.requestProgress = 'finish';
131 if (error.name !== 'AbortError') {
132 this.errorMessage = `Error fetching data from ${api_url} (${error})`;
133 this.requestProgress = 'finish';
137 if (endpoint_name !== 'status') this.lastApiRequestURL = api_url;
141 export const appState = new AppState();