Project

General

Profile

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

haketilo / content / repo_query.js @ 2bd35bc4

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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