/** * This file is part of Haketilo. * * Function: Getting available content for site from remote repositories. * * Copyright (C) 2021 Wojtek Kosior * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * As additional permission under GNU GPL version 3 section 7, you * may distribute forms of that code without the copy of the GNU * GPL normally required by section 4, provided you include this * license notice and, in case of non-source distribution, a URL * through which recipients can access the Corresponding Source. * If you modify file(s) with this exception, you may extend this * exception to your version of the file(s), but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. * * As a special exception to the GPL, any HTML file which merely * makes function calls to this code, and for that purpose * includes it by reference shall be deemed a separate work for * copyright law purposes. If you modify this code, you may extend * this exception to your version of the code, but you are not * obligated to do so. If you do not wish to do so, delete this * exception statement from your version. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. * * I, Wojtek Kosior, thereby promise not to sue for violation of this file's * license. Although I request that you do not make use this code in a * proprietary program, I am not going to enforce this in court. */ /* * IMPORTS_START * IMPORT make_ajax_request * IMPORT observables * IMPORT TYPE_PREFIX * IMPORT parse_json_with_schema * IMPORT matchers * IMPORTS_END */ const paths = { [TYPE_PREFIX.PAGE]: "/pattern", [TYPE_PREFIX.BAG]: "/bag", [TYPE_PREFIX.SCRIPT]: "/script", [TYPE_PREFIX.URL]: "/query" }; const queried_items = new Map(); const observable = observables.make(); function repo_query(prefix, item, repo_urls) { const key = prefix + item; const results = queried_items.get(key) || {}; queried_items.set(key, results); for (const repo_url of repo_urls) perform_query_against(key, repo_url, results); } const page_schema = { pattern: matchers.nonempty_string, payload: ["optional", matchers.component, "default", undefined] }; const bag_schema = { name: matchers.nonempty_string, components: ["optional", [matchers.component, "repeat"], "default", []] }; const script_schema = { name: matchers.nonempty_string, location: matchers.nonempty_string, sha256: matchers.sha256, }; const search_result_schema = [page_schema, "repeat"]; const schemas = { [TYPE_PREFIX.PAGE]: page_schema, [TYPE_PREFIX.BAG]: bag_schema, [TYPE_PREFIX.SCRIPT]: script_schema, [TYPE_PREFIX.URL]: search_result_schema } async function perform_query_against(key, repo_url, results) { if (results[repo_url] !== undefined) return; const prefix = key[0]; const item = key.substring(1); const result = {state: "started"}; results[repo_url] = result; const broadcast_msg = {prefix, item, results: {[repo_url]: result}}; observables.broadcast(observable, broadcast_msg); let state = "connection_error"; const query_url = `${repo_url}${paths[prefix]}?n=${encodeURIComponent(item)}`; try { let xhttp = await make_ajax_request("GET", query_url); if (xhttp.status === 200) { state = "parse_error"; result.response = parse_json_with_schema(schemas[prefix], xhttp.responseText); state = "completed"; } } catch (e) { console.log(e); } result.state = state; observables.broadcast(observable, broadcast_msg); } function subscribe_repo_query_results(cb) { observables.subscribe(observable, cb); for (const [key, results] of queried_items.entries()) cb({prefix: key[0], item: key.substring(1), results}); } function unsubscribe_repo_query_results(cb) { observables.unsubscribe(observable, cb); } /* * EXPORTS_START * EXPORT repo_query * EXPORT subscribe_repo_query_results * EXPORT unsubscribe_repo_query_results * EXPORTS_END */