/** * part of Hachette * Getting available content for site from remote repositories. * * Copyright (C) 2021 Wojtek Kosior * Redistribution terms are gathered in the `copyright' file. */ /* * 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 */