eve-esi-types 2.3.3 → 2.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ declare global {
2
+ interface String {
3
+ red: string;
4
+ green: string;
5
+ yellow: string;
6
+ blue: string;
7
+ magenta: string;
8
+ cyan: string;
9
+ }
10
+ }
11
+ /**
12
+ * @param {boolean} enable
13
+ */
14
+ export declare function defineColors(enable: boolean): void;
15
+ export declare function getLogger(banner: string, logSelector?: string): (...args: any[]) => void;
@@ -0,0 +1,102 @@
1
+ /*!
2
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
+ // Copyright (C) 2025 jeffy-g <hirotom1107@gmail.com>
4
+ // Released under the MIT license
5
+ // https://opensource.org/licenses/mit-license.php
6
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
+ */
8
+ /**
9
+ * @file eve-esi-types/lib/console-util.mts
10
+ */
11
+ import { isNode } from "./constants.mjs";
12
+ let colorsDefined = false;
13
+ /**
14
+ * @param {boolean} enable
15
+ */
16
+ export function defineColors(enable) {
17
+ if (isNode)
18
+ return;
19
+ if (!colorsDefined) {
20
+ colorsDefined = true;
21
+ Object.defineProperties(String.prototype, {
22
+ red: {
23
+ get() { return enable ? `<span style="color: red">${this}</span>` : this; }
24
+ },
25
+ green: {
26
+ get() { return enable ? `<span style="color: green">${this}</span>` : this; }
27
+ },
28
+ yellow: {
29
+ get() { return enable ? `<span style="color: yellow">${this}</span>` : this; }
30
+ },
31
+ blue: {
32
+ get() { return enable ? `<span style="color: blue">${this}</span>` : this; }
33
+ },
34
+ magenta: {
35
+ get() { return enable ? `<span style="color: #FF00FF">${this}</span>` : this; }
36
+ },
37
+ cyan: {
38
+ get() { return enable ? `<span style="color: #00FFFF">${this}</span>` : this; }
39
+ },
40
+ });
41
+ }
42
+ }
43
+ /**
44
+ * @param {string} jsonString
45
+ */
46
+ const jsonBeautify = (jsonString) => {
47
+ const re = /("(?:[^"\\]|\\.)*"(?:\s*:)?)|(-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)|\b(true|false)\b|\b(null)\b/gm;
48
+ return jsonString.replace(re, (m, key_or_str, num, bool, nul) => {
49
+ if (key_or_str) { // key
50
+ let clz;
51
+ const last = m.length - 1;
52
+ if (m[last] === ":") {
53
+ m = m.substring(0, last);
54
+ clz = "key";
55
+ }
56
+ else {
57
+ clz = "string";
58
+ }
59
+ let tag = `<span class="${clz}">${m}</span>`;
60
+ clz === "key" && (tag += ":");
61
+ return tag;
62
+ }
63
+ if (num) { // number
64
+ return `<span class="number">${m}</span>`;
65
+ }
66
+ if (bool) { // boolean
67
+ return `<span class="bool">${m}</span>`;
68
+ }
69
+ if (nul) { // null
70
+ return `<span class="nul">${m}</span>`;
71
+ }
72
+ return m;
73
+ });
74
+ };
75
+ export function getLogger(banner, logSelector = ".log-frame") {
76
+ /** @type {Element=} */
77
+ const logElement = isNode ? void 0 : document.querySelector(logSelector) || void 0;
78
+ defineColors(!!logElement);
79
+ if (!logElement) {
80
+ return console.log.bind(console, banner);
81
+ }
82
+ else {
83
+ /** @type {function(...any): void} */
84
+ const log = (...data) => {
85
+ let text = banner;
86
+ for (const d of data) {
87
+ if (typeof d === "object") {
88
+ const json = JSON.stringify(d, null, 2);
89
+ text += jsonBeautify(json);
90
+ }
91
+ else {
92
+ text += " " + d;
93
+ }
94
+ }
95
+ requestAnimationFrame(() => {
96
+ logElement.innerHTML += text + "\n";
97
+ logElement.scrollTop = 999999;
98
+ });
99
+ };
100
+ return log;
101
+ }
102
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Dummy import
3
+ * @import * as cc from "colors.ts";
4
+ */
5
+ /**
6
+ * will almost certainly be able to detect if you are in a nodejs environment
7
+ *
8
+ * @date 2020/5/9
9
+ */
10
+ export declare const isNode: boolean;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Dummy import
3
+ * @import * as cc from "colors.ts";
4
+ */
5
+ /**
6
+ * will almost certainly be able to detect if you are in a nodejs environment
7
+ *
8
+ * @date 2020/5/9
9
+ */
10
+ export const isNode = await (async () => {
11
+ let returnValue;
12
+ if (typeof process === "object") {
13
+ returnValue = typeof process.versions === "object" && /\d+\.\d+\.\d+/.test(process.versions.node);
14
+ if (returnValue) {
15
+ await import("colors.ts");
16
+ }
17
+ }
18
+ else {
19
+ // modId = "https://cdn.jsdelivr.net/npm/colors.ts@1.0.20/+esm";
20
+ returnValue = false;
21
+ }
22
+ return returnValue;
23
+ })();
@@ -1,3 +1,14 @@
1
+ /*!
2
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
+ // Copyright (C) 2025 jeffy-g <hirotom1107@gmail.com>
4
+ // Released under the MIT license
5
+ // https://opensource.org/licenses/mit-license.php
6
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
+ */
8
+ /**
9
+ * @file eve-esi-types/lib/esi-error-types.d.ts
10
+ * @since 2.3.2
11
+ */
1
12
 
2
13
  type TEVEErrorBase = {
3
14
  /**
@@ -34,8 +45,9 @@ export type TESIErrorStatMap = {
34
45
  * const res = await fetch("<URL with ESI endpoint>");
35
46
  * const status = res.status;
36
47
  * if (status >= 400) {
48
+ * const esiError = await res.json() as TESIErrorStatMap[typeof status];
37
49
  * const errorType: TESIErrorWithStat<typeof status> = {
38
- * status, ...res.json()
50
+ * status, ...esiError
39
51
  * };
40
52
  * console.log(errorType);
41
53
  * throw new Error(`message="${res.statusText}", status=${status}`);
@@ -43,7 +55,6 @@ export type TESIErrorStatMap = {
43
55
  * ```
44
56
  *
45
57
  * @date 2025/3/3
46
- * @since 2.4.0
47
58
  */
48
59
  export type TESIErrorWithStat<Stat extends TClientErrorStats | TServerErrorStats> = {
49
60
  status: Stat;
@@ -22,6 +22,6 @@ import type { IESIRequestFunction } from "../v2";
22
22
  * @param pathParams - An object of parameters to include in the request
23
23
  * @param options - An object of options to include in the request
24
24
  * @returns A Promise object containing the response data
25
- * @throws {ESIRequesError}
25
+ * @throws {util.ESIRequestError}
26
26
  */
27
27
  export declare const request: IESIRequestFunction<util.ESIRequestOptions>;
@@ -14,7 +14,7 @@ import * as util from "./rq-util.mjs";
14
14
  // constants, types
15
15
  // - - - - - - - - - - - - - - - - - - - -
16
16
  // shorthands
17
- const log = console.log;
17
+ const log = util.getUniversalLogger("[request-api]: ");
18
18
  const DEBUG = util.isDebug();
19
19
  /**
20
20
  * @typedef {import("../v2").IESIRequestFunction<util.ESIRequestOptions>} IESIRequestFunction
@@ -34,13 +34,11 @@ const DEBUG = util.isDebug();
34
34
  * @param pathParams - An object of parameters to include in the request
35
35
  * @param options - An object of options to include in the request
36
36
  * @returns A Promise object containing the response data
37
- * @throws {ESIRequesError}
37
+ * @throws {util.ESIRequestError}
38
38
  */
39
- // @ts-expect-error
40
- export const request = async (method, endpoint, pathParams, opt) => {
39
+ export const request = /** @type {IESIRequestFunction} */ (async (method, endpoint, pathParams, opt) => {
41
40
  if (typeof pathParams === "number") {
42
- // @ts-expect-error
43
- pathParams = [pathParams];
41
+ pathParams = /** @type {typeof pathParams} */ ([pathParams]);
44
42
  }
45
43
  if (Array.isArray(pathParams)) {
46
44
  endpoint = util.replaceCbt(endpoint, pathParams);
@@ -65,7 +63,7 @@ export const request = async (method, endpoint, pathParams, opt) => {
65
63
  catch (e) {
66
64
  log(e);
67
65
  }
68
- };
66
+ });
69
67
  //
70
68
  // implements rest methods of `request` (IESIRequestFunction)
71
69
  //
package/lib/rq-util.d.mts CHANGED
@@ -9,18 +9,16 @@
9
9
  // - - - - - - - - - - - - - - - - - - - -
10
10
  // imports
11
11
  // - - - - - - - - - - - - - - - - - - - -
12
+ /*!
13
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
14
+ // Copyright (C) 2025 jeffy-g <hirotom1107@gmail.com>
15
+ // Released under the MIT license
16
+ // https://opensource.org/licenses/mit-license.php
17
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
18
+ */
12
19
  import type { TESIRequestFunctionMethods } from "../v2";
13
20
  import type { TESIErrorStats } from "./esi-error-types";
14
- /**
15
- * Dummy import
16
- * @import * as cc from "colors.ts";
17
- */
18
- /**
19
- * will almost certainly be able to detect if you are in a nodejs environment
20
- *
21
- * @date 2020/5/9
22
- */
23
- export declare const isNode: boolean;
21
+ export { isNode } from "./constants.mjs";
24
22
  /**
25
23
  * this always `https://esi.evetech.net`
26
24
  */
@@ -62,12 +60,12 @@ export type ESIRequestOptions = {
62
60
  /**
63
61
  * simple named error class.
64
62
  */
65
- export declare class ESIRequesError extends Error {
63
+ export declare class ESIRequestError extends Error {
66
64
  }
67
65
  /**
68
66
  * throws when x-esi-error-limit-remain header value is "0". (http status: 420)
69
67
  */
70
- export declare class ESIErrorLimitReachedError extends ESIRequesError {
68
+ export declare class ESIErrorLimitReachedError extends ESIRequestError {
71
69
  constructor();
72
70
  valueOf(): number;
73
71
  }
@@ -99,7 +97,7 @@ export declare const handleSuccessResponse: (response: Response, endpointUrl: st
99
97
  *
100
98
  * @param {Response} res
101
99
  * @param {string} endpointUrl
102
- * @param {AbortController} abortable
100
+ * @param {AbortController=} abortable
103
101
  * @returns {Promise<void>}
104
102
  */
105
103
  export declare const handleESIError: (res: Response, endpointUrl: string, abortable?: AbortController) => Promise<void>;
@@ -123,13 +121,15 @@ export declare const isDebug: () => boolean;
123
121
  */
124
122
  export declare const is: (opt: string) => boolean;
125
123
  /**
124
+ * NOTE: In `initOptions`, if `auth=true`, then `token` can be set to a valid `accessToken` to successfully complete an authenticated request.
125
+ *
126
126
  * @param {string} method
127
127
  * @param {ESIRequestOptions} opt
128
- * @returns {{ rqopt: RequestInit, qss: Record<string, string> }}
128
+ * @returns {{ rqopt: RequestInit, qss: Record<string, any> }}
129
129
  */
130
130
  export declare const initOptions: (method: string, opt: ESIRequestOptions) => {
131
131
  rqopt: RequestInit;
132
- qss: Record<string, string>;
132
+ qss: Record<string, any>;
133
133
  };
134
134
  /**
135
135
  * fetch the extra pages
@@ -138,12 +138,12 @@ export declare const initOptions: (method: string, opt: ESIRequestOptions) => {
138
138
  * @template {any} T
139
139
  * @param {string} endpointUrl
140
140
  * @param {RequestInit} rqopt request options
141
- * @param {URLSearchParams} rqp queries
141
+ * @param {URLSearchParams} usp queries
142
142
  * @param {number} pc pageCount
143
143
  * @param {(minus?: number) => void=} increment
144
144
  * @returns {Promise<T | null>}
145
145
  */
146
- export declare const fetchP: <T extends unknown>(endpointUrl: string, rqopt: RequestInit, rqp: URLSearchParams, pc: number, increment?: (minus?: Truthy) => void) => Promise<T | null>;
146
+ export declare const fetchP: <T extends unknown>(endpointUrl: string, rqopt: RequestInit, usp: URLSearchParams, pc: number, increment?: (minus?: Truthy) => void) => Promise<T | null>;
147
147
  /** ### replace (C)urly (B)races (T)oken
148
148
  *
149
149
  * @example
@@ -158,7 +158,6 @@ export declare const fetchP: <T extends unknown>(endpointUrl: string, rqopt: Req
158
158
  */
159
159
  export declare const replaceCbt: <T extends unknown>(endpoint: T, ids: number[]) => T;
160
160
  /**
161
- *
162
161
  * @template {unknown} T
163
162
  * @param {T} endp this means endpoint url fragment like `/characters/{character_id}/` or `/characters/{character_id}/agents_research/`
164
163
  * + The version parameter is forced to apply `latest`
@@ -171,6 +170,7 @@ export declare const curl: <T extends unknown>(endp: T) => string;
171
170
  * @type {() => Promise<string>}
172
171
  */
173
172
  export declare function getSDEVersion(): Promise<string>;
173
+ export declare const getUniversalLogger: (banner: string, logSelector?: string) => (...args: any[]) => void;
174
174
  export declare function getLogger(): {
175
175
  clog: (...args: any[]) => void;
176
176
  rlog: (...args: any[]) => void;
package/lib/rq-util.mjs CHANGED
@@ -9,34 +9,14 @@
9
9
  // - - - - - - - - - - - - - - - - - - - -
10
10
  // imports
11
11
  // - - - - - - - - - - - - - - - - - - - -
12
- /**
13
- * Dummy import
14
- * @import * as cc from "colors.ts";
15
- */
16
- /**
17
- * will almost certainly be able to detect if you are in a nodejs environment
18
- *
19
- * @date 2020/5/9
20
- */
21
- export const isNode = await (async () => {
22
- let modId, returnValue;
23
- if (typeof process === "object") {
24
- modId = "colors.ts";
25
- // @ts-ignore
26
- returnValue = typeof process.versions === "object" && /\d+\.\d+\.\d+/.test(process.versions.node);
27
- }
28
- else {
29
- modId = "https://cdn.jsdelivr.net/npm/colors.ts@1.0.20/+esm";
30
- returnValue = false;
31
- }
32
- await import(modId);
33
- return returnValue;
34
- })();
12
+ import { isNode } from "./constants.mjs";
13
+ export { isNode } from "./constants.mjs";
14
+ import * as consoleUtil from "./console-util.mjs";
35
15
  // - - - - - - - - - - - - - - - - - - - -
36
16
  // constants, types
37
17
  // - - - - - - - - - - - - - - - - - - - -
38
18
  // shorthands
39
- const log = console.log;
19
+ const log = consoleUtil.getLogger("[request-util]:");
40
20
  const isArray = Array.isArray;
41
21
  /**
42
22
  * enable/disable console.log
@@ -52,12 +32,12 @@ export const BASE = "https://esi.evetech.net";
52
32
  /**
53
33
  * simple named error class.
54
34
  */
55
- export class ESIRequesError extends Error {
35
+ export class ESIRequestError extends Error {
56
36
  }
57
37
  /**
58
38
  * throws when x-esi-error-limit-remain header value is "0". (http status: 420)
59
39
  */
60
- export class ESIErrorLimitReachedError extends ESIRequesError {
40
+ export class ESIErrorLimitReachedError extends ESIRequestError {
61
41
  constructor() {
62
42
  super("Cannot continue ESI request because 'x-esi-error-limit-remain' is zero!");
63
43
  }
@@ -120,7 +100,7 @@ export const handleSuccessResponse = async (response, endpointUrl, requestOpt, u
120
100
  *
121
101
  * @param {Response} res
122
102
  * @param {string} endpointUrl
123
- * @param {AbortController} abortable
103
+ * @param {AbortController=} abortable
124
104
  * @returns {Promise<void>}
125
105
  */
126
106
  export const handleESIError = async (res, endpointUrl, abortable) => {
@@ -132,14 +112,13 @@ export const handleESIError = async (res, endpointUrl, abortable) => {
132
112
  status, ...esiError
133
113
  };
134
114
  // log ESI Error details
135
- console.warn(errorType);
115
+ log(errorType);
136
116
  if (status === 420) {
137
117
  abortable && abortable.abort();
138
118
  throw new ESIErrorLimitReachedError();
139
119
  }
140
120
  else {
141
- // console.log(res);
142
- throw new ESIRequesError(`${res.statusText} (status=${status}, url=${endpointUrl})`);
121
+ throw new ESIRequestError(`${res.statusText} (status=${status}, url=${endpointUrl})`);
143
122
  }
144
123
  };
145
124
  /** @satisfies {TESIErrorStats[]} */
@@ -182,7 +161,7 @@ export const isDebug = () => {
182
161
  * @returns {boolean}
183
162
  */
184
163
  export const is = (opt) => {
185
- if (typeof process === "object") {
164
+ if (isNode) {
186
165
  return process.argv.includes(`-${opt}`);
187
166
  }
188
167
  else {
@@ -206,9 +185,11 @@ export const is = (opt) => {
206
185
  return false;
207
186
  };
208
187
  /**
188
+ * NOTE: In `initOptions`, if `auth=true`, then `token` can be set to a valid `accessToken` to successfully complete an authenticated request.
189
+ *
209
190
  * @param {string} method
210
191
  * @param {ESIRequestOptions} opt
211
- * @returns {{ rqopt: RequestInit, qss: Record<string, string> }}
192
+ * @returns {{ rqopt: RequestInit, qss: Record<string, any> }}
212
193
  */
213
194
  export const initOptions = (method, opt) => {
214
195
  /** @type {RequestInit} */
@@ -219,7 +200,7 @@ export const initOptions = (method, opt) => {
219
200
  signal: opt.cancelable?.signal,
220
201
  headers: {}
221
202
  };
222
- /** @type {Record<string, string>} */
203
+ /** @type {Record<string, any>} */
223
204
  const qss = {
224
205
  // CAVEAT: If the language parameter is not set, some endpoints such as "/universe/ids/" may return incomplete results.
225
206
  // Therefore, the language parameter should always be set.
@@ -228,7 +209,8 @@ export const initOptions = (method, opt) => {
228
209
  if (opt.query) {
229
210
  // Object.assign(query, options.query); Object.assign is too slow
230
211
  const oqs = opt.query;
231
- Object.keys(oqs).forEach(k => qss[k] = oqs[k]);
212
+ for (const key in oqs)
213
+ qss[key] = oqs[key];
232
214
  }
233
215
  if (opt.auth) {
234
216
  // @ts-ignore The header is indeed an object
@@ -248,17 +230,17 @@ export const initOptions = (method, opt) => {
248
230
  * @template {any} T
249
231
  * @param {string} endpointUrl
250
232
  * @param {RequestInit} rqopt request options
251
- * @param {URLSearchParams} rqp queries
233
+ * @param {URLSearchParams} usp queries
252
234
  * @param {number} pc pageCount
253
235
  * @param {(minus?: number) => void=} increment
254
236
  * @returns {Promise<T | null>}
255
237
  */
256
- export const fetchP = async (endpointUrl, rqopt, rqp, pc, increment = () => { }) => {
238
+ export const fetchP = async (endpointUrl, rqopt, usp, pc, increment = () => { }) => {
257
239
  const rqs = [];
258
240
  for (let i = 2; i <= pc;) {
259
- rqp.set("page", (i++) + "");
241
+ usp.set("page", (i++) + "");
260
242
  increment();
261
- rqs.push(fetch(`${endpointUrl}?${rqp + ""}`, rqopt).then(res => res.json()).catch(reason => {
243
+ rqs.push(fetch(`${endpointUrl}?${usp + ""}`, rqopt).then(res => res.json()).catch(reason => {
262
244
  console.warn(reason);
263
245
  return [];
264
246
  }).finally(() => {
@@ -296,7 +278,6 @@ export const replaceCbt = (endpoint, ids) => {
296
278
  return endpoint.replace(/{([\w]+)}/g, $0 => ids[idx++] + "");
297
279
  };
298
280
  /**
299
- *
300
281
  * @template {unknown} T
301
282
  * @param {T} endp this means endpoint url fragment like `/characters/{character_id}/` or `/characters/{character_id}/agents_research/`
302
283
  * + The version parameter is forced to apply `latest`
@@ -330,9 +311,12 @@ export async function getSDEVersion() {
330
311
  return "sde-202Xxxxx-TRANQUILITY";
331
312
  }
332
313
  }
314
+ export const getUniversalLogger = (banner, logSelector = ".log-frame") => {
315
+ return consoleUtil.getLogger(banner, logSelector);
316
+ };
333
317
  export function getLogger() {
334
- const clog = console.log.bind(console, '- - -> Get the character data of "CCP Zoetrope"'.magenta);
335
- const rlog = console.log.bind(console, "- - -> Run ESI request".cyan);
318
+ const clog = consoleUtil.getLogger('- - -> Get the character data of "CCP Zoetrope"'.magenta);
319
+ const rlog = consoleUtil.getLogger("- - -> Run ESI request".cyan);
336
320
  return { clog, rlog };
337
321
  }
338
322
  /**
@@ -364,7 +348,6 @@ function fireWithoutAuth(fn, method, endpoint, pathParams, opt) {
364
348
  }
365
349
  return fn[method](endpoint, pathParams, opt);
366
350
  }
367
- // It should complete correctly.
368
351
  /**
369
352
  * #### Fire a request that does not require authentication.
370
353
  *
@@ -373,17 +356,18 @@ function fireWithoutAuth(fn, method, endpoint, pathParams, opt) {
373
356
  */
374
357
  export async function fireRequestsDoesNotRequireAuth(fn) {
375
358
  const { clog, rlog } = getLogger();
359
+ const ID_CCP_Zoetrope = 2112625428;
376
360
  try {
377
361
  // - - - - - - - - - - - -
378
362
  // Character
379
363
  // - - - - - - - - - - - -
380
364
  // Here, I borrow data from "CCP Zoetrope".
381
365
  clog();
382
- await fireWithoutAuth(fn, "get", "/characters/{character_id}/", 2112625428).then(log);
366
+ await fireWithoutAuth(fn, "get", "/characters/{character_id}/", ID_CCP_Zoetrope).then(log);
383
367
  clog('(portrait)');
384
- await fireWithoutAuth(fn, "get", "/characters/{character_id}/portrait/", 2112625428).then(log);
368
+ await fireWithoutAuth(fn, "get", "/characters/{character_id}/portrait/", ID_CCP_Zoetrope).then(log);
385
369
  clog('(affiliation)');
386
- const affiliation = await fireWithoutAuth(fn, "post", "/characters/affiliation/", { body: [2112625428] });
370
+ const affiliation = await fireWithoutAuth(fn, "post", "/characters/affiliation/", { body: [ID_CCP_Zoetrope] });
387
371
  log(affiliation);
388
372
  clog('(corporation)');
389
373
  await fireWithoutAuth(fn, "get", "/corporations/{corporation_id}/", affiliation[0].corporation_id).then(log);
@@ -396,6 +380,7 @@ export async function fireRequestsDoesNotRequireAuth(fn) {
396
380
  const ids = await fireWithoutAuth(fn, "post", "/universe/ids/", { body: ["the forge", "plex"] });
397
381
  log(ids.inventory_types, ids.regions);
398
382
  rlog(`get:/markets/${ids?.regions?.[0].id}/orders/?type_id=${ids?.inventory_types?.[0].id}, item PLEX`.green);
383
+ // in this case, "order_type" is required
399
384
  const orders = await fireWithoutAuth(fn, "get", "/markets/{region_id}/orders/", ids?.regions?.[0].id, {
400
385
  query: {
401
386
  // page: 1,
@@ -416,29 +401,23 @@ export async function fireRequestsDoesNotRequireAuth(fn) {
416
401
  // The following is code to observe the behavior of completion by generics.
417
402
  // Authentication is required, so an error will occur.
418
403
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
419
- let ok = await fireWithoutAuth(fn, "get", "/characters/{character_id}/ship/", 994562, {
404
+ let willFailed = await fireWithoutAuth(fn, "get", "/characters/{character_id}/ship/", ID_CCP_Zoetrope, {
420
405
  auth: true,
421
406
  ignoreError: true,
422
407
  token: "token.token.token"
423
408
  });
424
409
  // in this case, "categories" and "search" is required
425
- await fireWithoutAuth(fn, "get", "/characters/{character_id}/search/", 994562, {
410
+ await fireWithoutAuth(fn, "get", "/characters/{character_id}/search/", ID_CCP_Zoetrope, {
426
411
  query: {
427
412
  categories: ["agent"],
428
413
  search: "ok"
429
414
  },
430
415
  auth: true
431
416
  });
432
- // in this case, "order_type" is required
433
- await fireWithoutAuth(fn, "get", "/markets/{region_id}/orders/", 994562, {
434
- query: {
435
- order_type: "all"
436
- },
437
- });
438
417
  // TODO: want TypeScript semantics to throw an error because there is a required query parameter, but it's not possible
439
418
  // Or rather, I don't know how to do it.
440
419
  await fireWithoutAuth(fn, "get", "/characters/{character_id}/search/");
441
- log(ok);
420
+ log(willFailed);
442
421
  }
443
422
  catch (e) {
444
423
  console.error("Failed to request -", e);
@@ -18,9 +18,9 @@ import type { ESIRequestOptions } from "./rq-util.mjs";
18
18
  * const esiRequest = taggedApi.injectESIRequestBody(...);
19
19
  * const ret = await esiRequest.universe.get("/universe/structures/", { query: { filter: "market" }});
20
20
  *
21
- * @template {Record<string, unknown>} Opt
22
- * @param {TESIRequestFunctionSignature<{}>} requestBody
23
- * @returns {XESI.TaggedESIRequestMap}
21
+ * @template {Record<string, unknown>} Opt - The options type for the request.
22
+ * @param {TESIRequestFunctionSignature<Opt>} requestBody - The function signature for the ESI request.
23
+ * @returns {XESI.TaggedESIRequestMap} - The tagged ESI request map.
24
24
  * @since 2.3
25
25
  */
26
26
  export declare function injectESIRequestBody<Opt extends Record<string, unknown>>(requestBody: TESIRequestFunctionSignature<Opt>): XESI.TaggedESIRequestMap<Opt>;
@@ -29,6 +29,7 @@ export declare function injectESIRequestBody<Opt extends Record<string, unknown>
29
29
  */
30
30
  /**
31
31
  * Injects the minimal implementation of ESI requests into `XESI.TaggedESIRequestMap`.
32
+ *
32
33
  * @since 2.3
33
34
  * @type {XESI.TaggedESIRequestMap<ESIRequestOptions>}
34
35
  */
@@ -10,11 +10,14 @@
10
10
  * @file eve-esi-types/lib/tagged-request-api.mts
11
11
  */
12
12
  import { request } from "./request-api.mjs";
13
+ /**
14
+ * @import { TESIRequestFunctionMethods } from "../v2"
15
+ */
13
16
  /**
14
17
  * @typedef {`${string}${"" | `,${string}`}`} TMethodList
15
18
  */
16
19
  /** @satisfies {`${XESI.ESITags}:${TMethodList}`[]} */
17
- const ESITagsWithMethodList = [
20
+ const ESITagMethodMapping = [
18
21
  "Alliance:get", "Assets:get,post",
19
22
  "Calendar:get,put", "Character:get,post",
20
23
  "Clones:get", "Contacts:get,post,put,delete",
@@ -43,31 +46,39 @@ const ESITagsWithMethodList = [
43
46
  * const esiRequest = taggedApi.injectESIRequestBody(...);
44
47
  * const ret = await esiRequest.universe.get("/universe/structures/", { query: { filter: "market" }});
45
48
  *
46
- * @template {Record<string, unknown>} Opt
47
- * @param {TESIRequestFunctionSignature<{}>} requestBody
48
- * @returns {XESI.TaggedESIRequestMap}
49
+ * @template {Record<string, unknown>} Opt - The options type for the request.
50
+ * @param {TESIRequestFunctionSignature<Opt>} requestBody - The function signature for the ESI request.
51
+ * @returns {XESI.TaggedESIRequestMap} - The tagged ESI request map.
49
52
  * @since 2.3
50
53
  */
51
54
  export function injectESIRequestBody(requestBody) {
52
55
  const rq = /** @type {XESI.TaggedESIRequestMap<Opt>} */ ({});
53
- for (const tagEntry of ESITagsWithMethodList) {
56
+ // DEVNOTE: 2025/03/08 - In reality, you only need one function instance for each of "get", "post", "put", and "delete",
57
+ // so you can just refer to the cached functions as a map.
58
+ const methodMap = /** @type {TESIRequestFunctionMethods<Opt>} */ ({});
59
+ /** @type {TESIEntryMethod[]} */ (["get", "post", "put", "delete"]).forEach((method) => {
60
+ methodMap[method] = /** @type {TESIRequestFunctionEachMethod<typeof method, Opt>} */ ((e, params, opt) => requestBody(method, e, params, opt));
61
+ });
62
+ for (const tagEntry of ESITagMethodMapping) {
54
63
  const [tag, methodList] = /** @type {[tag: XESI.ESITags, methods: TMethodList]} */ (tagEntry.split(":"));
55
64
  const methods = /** @type {TESIEntryMethod[]} */ (methodList.split(","));
56
65
  const entry = /** @type {XESI.ESITaggedEndpointRequest<typeof tag, Opt>} */ ({});
57
66
  for (const method of methods) {
67
+ // However, from the point of view of type annotation, the parameters are different, so you need to cast it as `as type` instead of `satisfies`.
58
68
  // @ts-expect-error
59
- entry[method] = /** @satisfies {XESI.TaggedEndpointRequestFunction<typeof method, typeof tag>} */ ((e, params, opt) => requestBody(method, e, params, opt));
69
+ entry[method] = /** @type {XESI.TaggedEndpointRequestFunction<typeof method, typeof tag, Opt>} */ (methodMap[method]);
60
70
  }
61
71
  const camelCased = /** @type {XESI.LCamelCase<XESI.ESITags>} */ (tag[0].toLowerCase() + tag.slice(1).replace(/\s(.)/g, "$1"));
62
72
  rq[camelCased] = entry;
63
73
  }
64
- return rq;
74
+ return Object.freeze(rq);
65
75
  }
66
76
  /**
67
77
  * @import { ESIRequestOptions } from "./rq-util.mjs";
68
78
  */
69
79
  /**
70
80
  * Injects the minimal implementation of ESI requests into `XESI.TaggedESIRequestMap`.
81
+ *
71
82
  * @since 2.3
72
83
  * @type {XESI.TaggedESIRequestMap<ESIRequestOptions>}
73
84
  */