diff options
Diffstat (limited to 'content')
-rw-r--r-- | content/activity_info_server.js | 35 | ||||
-rw-r--r-- | content/repo_query.js | 113 |
2 files changed, 148 insertions, 0 deletions
diff --git a/content/activity_info_server.js b/content/activity_info_server.js index 8435377..81a25fb 100644 --- a/content/activity_info_server.js +++ b/content/activity_info_server.js @@ -11,12 +11,20 @@ * IMPORTS_START * IMPORT listen_for_connection * IMPORT CONNECTION_TYPE + * IMPORT repo_query + * IMPORT subscribe_repo_query_results + * IMPORT unsubscribe_repo_query_results * IMPORTS_END */ var activities = []; var ports = new Set(); +function report_activity_oneshot(name, data, port) +{ + port.postMessage([name, data]); +} + function report_activity(name, data) { const activity = [name, data]; @@ -36,6 +44,22 @@ function report_settings(settings) report_activity("settings", settings); } +function report_repo_query_action(update, port) +{ + report_activity_oneshot("repo_query_action", update, port); +} + +function trigger_repo_query(query_specifier) +{ + repo_query(...query_specifier); +} + +function handle_disconnect(port, report_action) +{ + ports.delete(port) + unsubscribe_repo_query_results(report_action); +} + function new_connection(port) { console.log("new activity info connection!"); @@ -44,6 +68,17 @@ function new_connection(port) for (const activity of activities) port.postMessage(activity); + + const report_action = u => report_repo_query_action(u, port); + subscribe_repo_query_results(report_action); + + /* + * So far the only thing we expect to receive is repo query order. Once more + * possibilities arrive, we will need to complicate this listener. + */ + port.onMessage.addListener(trigger_repo_query); + + port.onDisconnect.addListener(() => handle_disconnect(port, report_action)); } function start_activity_info_server() diff --git a/content/repo_query.js b/content/repo_query.js new file mode 100644 index 0000000..3708108 --- /dev/null +++ b/content/repo_query.js @@ -0,0 +1,113 @@ +/** + * 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 + */ |