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.