Project

General

Profile

Download (2.71 KB) Statistics
| Branch: | Tag: | Revision:

haketilo / content / repo_query.js @ 792fbe18

1
/**
2
 * part of Hachette
3
 * Getting available content for site from remote repositories.
4
 *
5
 * Copyright (C) 2021 Wojtek Kosior
6
 * Redistribution terms are gathered in the `copyright' file.
7
 */
8

    
9
/*
10
 * IMPORTS_START
11
 * IMPORT make_ajax_request
12
 * IMPORT observables
13
 * IMPORT TYPE_PREFIX
14
 * IMPORT parse_json_with_schema
15
 * IMPORT matchers
16
 * IMPORTS_END
17
 */
18

    
19
const paths = {
20
    [TYPE_PREFIX.PAGE]: "/pattern",
21
    [TYPE_PREFIX.BAG]: "/bag",
22
    [TYPE_PREFIX.SCRIPT]: "/script",
23
    [TYPE_PREFIX.URL]: "/query"
24
};
25

    
26
const queried_items = new Map();
27
const observable = observables.make();
28

    
29
function repo_query(prefix, item, repo_urls)
30
{
31
    const key = prefix + item;
32

    
33
    const results = queried_items.get(key) || {};
34
    queried_items.set(key, results);
35

    
36
    for (const repo_url of repo_urls)
37
	perform_query_against(key, repo_url, results);
38
}
39

    
40
const page_schema = {
41
    pattern: matchers.nonempty_string,
42
    payload: ["optional", matchers.component, "default", undefined]
43
};
44
const bag_schema = {
45
    name: matchers.nonempty_string,
46
    components: ["optional", [matchers.component, "repeat"], "default", []]
47
};
48
const script_schema = {
49
    name: matchers.nonempty_string,
50
    location: matchers.nonempty_string,
51
    sha256: matchers.sha256,
52
};
53
const search_result_schema = [page_schema, "repeat"];
54

    
55
const schemas = {
56
    [TYPE_PREFIX.PAGE]: page_schema,
57
    [TYPE_PREFIX.BAG]: bag_schema,
58
    [TYPE_PREFIX.SCRIPT]: script_schema,
59
    [TYPE_PREFIX.URL]: search_result_schema
60
}
61

    
62
async function perform_query_against(key, repo_url, results)
63
{
64
    if (results[repo_url] !== undefined)
65
	return;
66

    
67
    const prefix = key[0];
68
    const item = key.substring(1);
69
    const result = {state: "started"};
70
    results[repo_url] = result;
71

    
72
    const broadcast_msg = {prefix, item, results: {[repo_url]: result}};
73
    observables.broadcast(observable, broadcast_msg);
74

    
75
    let state = "connection_error";
76
    const query_url =
77
	  `${repo_url}${paths[prefix]}?n=${encodeURIComponent(item)}`;
78

    
79
    try {
80
	let xhttp = await make_ajax_request("GET", query_url);
81
	if (xhttp.status === 200) {
82
	    state = "parse_error";
83
	    result.response =
84
		parse_json_with_schema(schemas[prefix], xhttp.responseText);
85
	    state = "completed";
86
	}
87
    } catch (e) {
88
	console.log(e);
89
    }
90

    
91
    result.state = state;
92
    observables.broadcast(observable, broadcast_msg);
93
}
94

    
95
function subscribe_repo_query_results(cb)
96
{
97
    observables.subscribe(observable, cb);
98
    for (const [key, results] of queried_items.entries())
99
	cb({prefix: key[0], item: key.substring(1), results});
100
}
101

    
102
function unsubscribe_repo_query_results(cb)
103
{
104
    observables.unsubscribe(observable, cb);
105
}
106

    
107
/*
108
 * EXPORTS_START
109
 * EXPORT repo_query
110
 * EXPORT subscribe_repo_query_results
111
 * EXPORT unsubscribe_repo_query_results
112
 * EXPORTS_END
113
 */
(5-5/5)