PageSourceSearch

https://caldariprimeponyclub.com/src/api/CjsESIMarket.mjs

js caldariprimeponyclub.com collected 2026-10-07 19:37:59 UTC 3,243 bytes, 119 lines download raw bytes

1export class CjsESIMarket
2{
3
4    constructor({
5        baseURL = "/api/market",
6        origin = globalThis.location?.origin || "http://localhost",
7        fetchImpl = globalThis.fetch
8    } = {})
9    {
10        if (typeof fetchImpl !== "function") throw new TypeError("CjsESIMarket requires fetch");
11
12        this.baseURL = new URL(`${baseURL.replace(/\/$/, "")}/`, origin);
13
14        this.fetchImpl = fetchImpl.bind(globalThis);
15    }
16
17    GetRegions(selectedRegionID = null, { signal } = {})
18    {
19        const regionID = selectedRegionID === null ? null : positiveID(selectedRegionID, "selectedRegionID");
20
21        return this.#Json("regions", { selectedRegionID: regionID }, signal);
22    }
23
24    BrowseTypes({ signal } = {})
25    {
26        return this.#Json("browse", null, signal);
27    }
28
29    SearchTypes(query, { regionID = null, signal } = {})
30    {
31        query = String(query ?? "").trim();
32        if (!query || query.length > 128) throw new TypeError("query must contain 1 to 128 characters");
33
34        const selectedRegionID = regionID === null ? null : positiveID(regionID, "regionID");
35
36        return this.#Json("search", { q: query, regionID: selectedRegionID }, signal);
37    }
38
39    GetType(typeID, { signal } = {})
40    {
41        typeID = positiveID(typeID, "typeID");
42
43        return this.#Json(`types/${typeID}`, null, signal);
44    }
45
46    GetOrders(typeID, regionID, { signal } = {})
47    {
48        typeID = positiveID(typeID, "typeID");
49        regionID = positiveID(regionID, "regionID");
50
51        return this.#Json(`regions/${regionID}/orders`, { typeID }, signal);
52    }
53
54    GetHistory(typeID, regionID, { signal } = {})
55    {
56        typeID = positiveID(typeID, "typeID");
57        regionID = positiveID(regionID, "regionID");
58
59        return this.#Json(`regions/${regionID}/history`, { typeID }, signal);
60    }
61
62    async GetMarket(typeID, regionID, { signal } = {})
63    {
64        typeID = positiveID(typeID, "typeID");
65        regionID = positiveID(regionID, "regionID");
66
67        return this.#Json(`regions/${regionID}/types/${typeID}`, null, signal);
68    }
69
70    GetStatus({ signal } = {})
71    {
72        return this.#Json("status", null, signal);
73    }
74
75    async #Json(path, query, signal)
76    {
77        const url = new URL(path, this.baseURL);
78
79        for (const [ name, value ] of Object.entries(query ?? {}))
80        {
81            if (value !== null && value !== undefined && value !== "") url.searchParams.set(name, value);
82        }
83
84        const response = await this.fetchImpl(url, {
85            credentials: "same-origin",
86            headers: { Accept: "application/json" },
87            signal
88        });
89
90        if (response.ok) return response.json();
91
92        let message = `Market request failed (${response.status})`;
93
94        try
95        {
96            const problem = await response.json();
97
98            if (problem?.error) message = problem.error;
99        }
100        catch
101        {
102
103        }
104
105        const error = new Error(message);
106
107        error.statusCode = response.status;
108        throw error;
109    }
110
111}
112
113function positiveID(value, name)
114{
115    const id = Number(value);
116
117    if (Number.isSafeInteger(id) && id > 0) return id;
118    throw new TypeError(`${name} must be a positive integer`);
119}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.