eve-esi-types 2.2.0 → 2.2.4

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.
package/v2/index.d.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  * THIS TSD IS AUTO GENERATED, DO NOT EDIT
10
10
  *
11
11
  * @file eve-esi-types/v2/index.d.ts
12
- * @summary This file is auto-generated and defines version 2.2.0 of the EVE Online ESI response types.
12
+ * @summary This file is auto-generated and defines version 2.2.4 of the EVE Online ESI response types.
13
13
  */
14
14
  import "./get_alliances_ok.d.ts";
15
15
  import "./get_alliances_alliance_id_ok.d.ts";
@@ -203,12 +203,112 @@ import "./extra-types.d.ts";
203
203
  */
204
204
  type RequireThese<T, K extends keyof T> = T & Required<Pick<T, K>>;
205
205
 
206
+ /**
207
+ * Represents a function that can make ESI requests with various HTTP methods.
208
+ *
209
+ * @template ActualOpt - The actual type of the options.
210
+ *
211
+ * @example
212
+ * ```ts
213
+ * // @ ts-expect-error
214
+ * export const request: IESIRequestFunction<ESIRequestOptions> = (method, endpoint, pathParams, opt) => {
215
+ * // Implementation for "get" | "post" | "put" | "delete" request
216
+ * };
217
+ * // You can easily implement "get" | "post" | "put" | "delete" requests
218
+ * // with code like the following:
219
+ * (["get", "post", "put", "delete"] as (keyof typeof request)[]).forEach((method) => {
220
+ * request[method] = function (this: typeof request, endpoint, params, opt) {
221
+ * return this(method, endpoint, params, opt);
222
+ * } as TESIRequestFunctionEachMethod<typeof method>;
223
+ * });
224
+ * ```
225
+ */
226
+ export interface IESIRequestFunction<ActualOpt>
227
+ extends TESIRequestFunctionSignature<ActualOpt>, TESIRequestFunctionMethods<ActualOpt> {
228
+ }
229
+
230
+ /**
231
+ * Represents the methods available for making ESI requests.
232
+ *
233
+ * + This interface is used when you already have implementation code such as
234
+ * TESIRequestFunctionSignature and you want to implement additional shorthand methods.
235
+ *
236
+ * @template ActualOpt - The actual type of the options.
237
+ *
238
+ * @example
239
+ * ```ts
240
+ * export const request: TESIRequestFunctionSignature<ESIRequestOptions> = (method, endpoint, pathParams, opt) => {
241
+ * // Implementation for "get" | "post" | "put" | "delete" request
242
+ * };
243
+ * // You can easily implement "get" | "post" | "put" | "delete" requests
244
+ * // with code like the following:
245
+ * const esiMethods = {} as TESIRequestFunctionMethods<ESIRequestOptions>;
246
+ * (["get", "post", "put", "delete"] as (keyof TESIRequestFunctionMethods)[]).forEach((method) => {
247
+ * esiMethods[method] = function (endpoint, params, opt) {
248
+ * return request(method, endpoint, params, opt);
249
+ * } as TESIRequestFunctionEachMethod<typeof method>;
250
+ * });
251
+ * ```
252
+ */
253
+ export type TESIRequestFunctionMethods<ActualOpt = {}> = {
254
+ [method in TESIEntryMethod]: TESIRequestFunctionEachMethod<method, ActualOpt>;
255
+ }
256
+
206
257
  declare global {
207
258
 
208
259
  /**
209
- * is parameterized path
260
+ * ### ESI request function all in one signature
261
+ *
262
+ * TESIRequestFunctionSignature is a type that defines the signature of an ESI request function.
263
+ *
264
+ * This function sends a request to a specified endpoint and returns a response.
265
+ *
266
+ * @template ActualOpt - The actual type of the option.
267
+ * Required parameters inferred by typescript are merged.
268
+ * @template M - The HTTP method to use for the request
269
+ * @template EP - The Path of the ESI endpoint to send the request to
270
+ * @template P2 - Parameters to include in the request
271
+ * @template Opt - Options to include in the request
272
+ * If there is a required parameter, its type will be merged with `ActualOpt`
273
+ * @template R - The response type
210
274
  */
211
- type IsParameterizedPath<EP, A, B> = EP extends `${string}/{${string}}/${string | ""}` ? A: B;
275
+ type TESIRequestFunctionSignature<ActualOpt> = <
276
+ M extends TESIEntryMethod,
277
+ EP extends keyof TESIResponseOKMap[M],
278
+ P2 extends IfParameterizedPath<EP, Opt>,
279
+ Opt extends IdentifyParameters<TESIResponseOKMap[M][EP], ActualOpt>,
280
+ R extends InferESIResponseResult<M, EP>
281
+ >(method: M, endpoint: EP, pathParams?: P2, options?: Opt) => Promise<R>;
282
+
283
+ /**
284
+ * Represents a function that makes an ESI request using a specific HTTP method.
285
+ *
286
+ * @template M - The HTTP method to use for the request (e.g., "get", "post").
287
+ * @template ActualOpt - The actual type of the options to include in the request.
288
+ *
289
+ * @param endpoint - The path of the ESI endpoint to send the request to.
290
+ * @param pathParams - An optional parameter that can be a number, an array of numbers, or other parameters
291
+ * depending on whether the path is parameterized.
292
+ * @param options - An optional object containing additional options for the request.
293
+ *
294
+ * @returns A Promise object containing the response data, with the type inferred based on the method and endpoint.
295
+ */
296
+ type TESIRequestFunctionEachMethod<M extends TESIEntryMethod, ActualOpt = {}> = <
297
+ EP extends keyof TESIResponseOKMap[M],
298
+ P2 extends IfParameterizedPath<EP, Opt>,
299
+ Opt extends IdentifyParameters<TESIResponseOKMap[M][EP], ActualOpt>,
300
+ R extends InferESIResponseResult<M, EP>
301
+ >(endpoint: EP, pathParams?: P2, options?: Opt) => Promise<R>;
302
+
303
+ // /**
304
+ // * is parameterized path
305
+ // */
306
+ // type IsParameterizedPath<EP, A, B> = EP extends `${string}/{${string}}/${string | ""}` ? A: B;
307
+ /**
308
+ * if parameterized path then specify number type, otherwise will be `Opt` type.
309
+ */
310
+ type IfParameterizedPath<EP, Opt> = EP extends `${string}/{${string}}/${string | ""}` ? number | number[]: Opt;
311
+
212
312
  /**
213
313
  * Identifies the required parameters for a given entry type.
214
314
  *
package/v2.d.mts CHANGED
@@ -11,7 +11,7 @@ import { type ESIRequestOptions } from "./rq-util.mjs";
11
11
  * fire ESI request
12
12
  * @template {TESIEntryMethod} M
13
13
  * @template {keyof TESIResponseOKMap[M]} EP
14
- * @template {IsParameterizedPath<EP, number | number[], Opt>} P2
14
+ * @template {IfParameterizedPath<EP, Opt>} P2
15
15
  * @template {IdentifyParameters<TESIResponseOKMap[M][EP], ESIRequestOptions>} Opt
16
16
  * @template {InferESIResponseResult<M, EP>} R
17
17
  *
@@ -23,10 +23,4 @@ import { type ESIRequestOptions } from "./rq-util.mjs";
23
23
  * @throws
24
24
  * @async
25
25
  */
26
- export declare function fire<
27
- M extends TESIEntryMethod,
28
- EP extends keyof TESIResponseOKMap[M],
29
- Opt extends IdentifyParameters<TESIResponseOKMap[M][EP], ESIRequestOptions>,
30
- P2 extends IsParameterizedPath<EP, number | number[], Opt>,
31
- R extends InferESIResponseResult<M, EP>
32
- >(mthd: M, endp: EP, pathParams?: P2, opt?: Opt): Promise<R>;
26
+ export declare function fire<M extends TESIEntryMethod, EP extends keyof TESIResponseOKMap[M], P2 extends IfParameterizedPath<EP, Opt>, Opt extends IdentifyParameters<TESIResponseOKMap[M][EP], ESIRequestOptions>, R extends InferESIResponseResult<M, EP>>(mthd: M, endp: EP, pathParams?: P2, opt?: Opt): Promise<R>;
package/v2.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // import type { TESIResponseOKMap } from "eve-esi-types";
2
- import { curl, replaceCbt, fetchP, ESIRequesError, ESIErrorLimitReachedError } from "./rq-util.mjs";
2
+ import { curl, fetchP, replaceCbt, getSDEVersion, ESIRequesError, initOptions, isDebug, ESIErrorLimitReachedError, fireRequestsDoesNotRequireAuth } from "./rq-util.mjs";
3
3
  // - - - - - - - - - - - - - - - - - - - -
4
4
  // constants, types
5
5
  // - - - - - - - - - - - - - - - - - - - -
@@ -9,19 +9,10 @@ const isArray = Array.isArray;
9
9
  /**
10
10
  * enable/disable console.log
11
11
  */
12
- let LOG = false;
12
+ let LOG = isDebug();
13
13
  /**
14
14
  * @typedef {import("./v2").TESIResponseOKMap} TESIResponseOKMap
15
- */
16
- /**
17
- * @typedef {`${string}.${string}.${string}`} TAcccessToken __{Header}.{Payload}.{Signature}__
18
- * @typedef ESIRequestOptions
19
- * @prop {Record<string, any>} [query] query params for ESI request.
20
- * @prop {any} [body] will need it for `POST` request etc.
21
- * @prop {true=} [auth] Can be an empty object if no authentication is required.description
22
- * @prop {TAcccessToken} [token] Can be an empty object if no authentication is required.description
23
- * @prop {boolean} [ignoreError] if want response data with ignore error then can be set to `true`.
24
- * @prop {AbortController} [cancelable] cancel request immediately
15
+ * @typedef {import("./rq-util.mjs").ESIRequestOptions} ESIRequestOptions
25
16
  */
26
17
  // - - - - - - - - - - - - - - - - - - - -
27
18
  // module vars, functions
@@ -34,44 +25,11 @@ const incrementAx = (minus) => minus ? ax-- : ax++;
34
25
  // - - - - - - - - - - - - - - - - - - - -
35
26
  // main functions
36
27
  // - - - - - - - - - - - - - - - - - - - -
37
- // It should complete correctly.
38
- async function getEVEStatus() {
39
- try {
40
- const ok = await fire("get", "/characters/{character_id}/ship/", 994562, { auth: true });
41
- // query patameter `filter` is optional
42
- await fire("get", "/universe/structures/", {
43
- query: {
44
- // filter: "market"
45
- }
46
- });
47
- // in this case, "categories" and "search" is required
48
- await fire("get", "/characters/{character_id}/search/", 994562, {
49
- query: {
50
- categories: ["agent"],
51
- search: "ok"
52
- },
53
- auth: true
54
- });
55
- // in this case, "order_type" is required
56
- await fire("get", "/markets/{region_id}/orders/", 994562, {
57
- query: {
58
- order_type: "all"
59
- },
60
- });
61
- // TODO: want TypeScript semantics to throw an error because there is a required query parameter, but it's not possible
62
- await fire("get", "/characters/{character_id}/search/");
63
- console.log(ok);
64
- }
65
- catch (error) {
66
- console.error("Failed to get character ship -", error);
67
- }
68
- return fire("get", "/status/");
69
- }
70
28
  /**
71
29
  * fire ESI request
72
30
  * @template {TESIEntryMethod} M
73
31
  * @template {keyof TESIResponseOKMap[M]} EP
74
- * @template {IsParameterizedPath<EP, number | number[], Opt>} P2
32
+ * @template {IfParameterizedPath<EP, Opt>} P2
75
33
  * @template {IdentifyParameters<TESIResponseOKMap[M][EP], ESIRequestOptions>} Opt
76
34
  * @template {InferESIResponseResult<M, EP>} R
77
35
  *
@@ -85,73 +43,42 @@ async function getEVEStatus() {
85
43
  */
86
44
  export async function fire(mthd, endp, pathParams, opt) {
87
45
  if (typeof pathParams === "number") {
88
- // @ts-ignore
46
+ // @ts-expect-error
89
47
  pathParams = [pathParams]; // as unknown as P2;
90
48
  }
91
49
  if (isArray(pathParams)) {
92
- // @ts-ignore actualy endp is string
50
+ // @ts-expect-error actualy endp is string
93
51
  endp = replaceCbt(endp, pathParams);
94
52
  }
95
53
  // When only options are provided
96
54
  /** @type {Opt} */
97
55
  // @ts-ignore
98
- const actualOpt = pathParams || opt || {};
99
- /** @type {RequestInit} */
100
- const rqopt = {
101
- method: mthd,
102
- mode: "cors",
103
- cache: "no-cache",
104
- // @ts-ignore
105
- signal: actualOpt.cancelable?.signal,
106
- headers: {}
107
- };
108
- const qss = {
109
- language: "en",
110
- };
111
- if (actualOpt.query) {
112
- // Object.assign(queries, options.queries); Object.assign is too slow
113
- const oqs = actualOpt.query;
114
- for (const k of Object.keys(oqs)) {
115
- qss[k] = oqs[k];
116
- }
117
- }
118
- // DEVNOTE: when datasource is not empty string. (e.g - "singularity"
119
- // in this case must specify datasource.
120
- // disabled since `REMOVING DATASOURCE SINGULARITY`
121
- // if (actualOpt.datasource === "singularity") {
122
- // actualOpt.datasource = "tranquility";
123
- // }
124
- if (actualOpt.auth) {
125
- // @ts-ignore The header is indeed an object
126
- rqopt.headers.authorization = `Bearer ${actualOpt.token}`;
127
- }
128
- if (actualOpt.body) { // means "POST" method etc
129
- // @ts-ignore The header is indeed an object
130
- rqopt.headers["content-type"] = "application/json";
131
- rqopt.body = JSON.stringify(actualOpt.body);
132
- }
133
- // @ts-ignore actualy endp is string
56
+ const actualOpt = opt || pathParams || {};
57
+ const { rqopt, qss } = initOptions(mthd, actualOpt);
58
+ // @ts-expect-error actualy endp is string
134
59
  const endpointUrl = curl(endp);
60
+ const up = new URLSearchParams(qss);
61
+ const url = `${endpointUrl}${up.size ? `?${up}` : ""}`;
62
+ LOG && log(url);
135
63
  ax++;
136
64
  try {
137
- // @ts-ignore A silly type error will appear, but ignore it.
138
- const res = await fetch(`${endpointUrl}?${new URLSearchParams(qss) + ""}`, rqopt).finally(() => ax--);
139
- const stat = res.status;
65
+ const res = await fetch(url, rqopt).finally(() => ax--);
66
+ const { status } = res;
140
67
  if (!res.ok && !actualOpt.ignoreError) {
141
- if (stat === 420) {
68
+ if (status === 420) {
142
69
  actualOpt.cancelable && actualOpt.cancelable.abort();
143
70
  throw new ESIErrorLimitReachedError();
144
71
  }
145
72
  else {
146
73
  // console.log(res);
147
- throw new ESIRequesError(`${res.statusText} (status=${stat})`);
74
+ throw new ESIRequesError(`${res.statusText} (status=${status})`);
148
75
  }
149
76
  }
150
77
  else {
151
78
  // DEVNOTE: - 204 No Content
152
- if (stat === 204) {
79
+ if (status === 204) {
153
80
  // this result is empty, decided to return status code.
154
- return /** @type {R} */ ({ status: stat });
81
+ return /** @type {R} */ ({ status });
155
82
  }
156
83
  /** @type {R} */
157
84
  const data = await res.json();
@@ -161,19 +88,19 @@ export async function fire(mthd, endp, pathParams, opt) {
161
88
  }
162
89
  // - - - - x-pages response.
163
90
  // +undefined is NaN
164
- // @ts-ignore becouse +null is 0
91
+ // @ts-expect-error becouse +null is 0
165
92
  const pc = +res.headers.get("x-pages");
166
93
  // has remaining pages? NaN > 1 === false !isNaN(pageCount)
167
94
  if (pc > 1) {
168
95
  LOG && log('found "x-pages" header, pages: %d', pc);
169
- const remData = await fetchP(endpointUrl, rqopt, qss, pc, incrementAx);
96
+ const remData = await fetchP(endpointUrl, rqopt, up, pc, incrementAx);
170
97
  // finally, decide product data.
171
98
  if (isArray(data) && isArray(remData)) {
172
99
  // DEVNOTE: 2019/7/23 15:01:48 - types
173
100
  return /** @type {R} */ (data.concat(remData));
174
101
  }
175
102
  else {
176
- // @ts-ignore TODO: fix type
103
+ // @ts-expect-error TODO: fix type
177
104
  remData && Object.assign(data, remData);
178
105
  }
179
106
  }
@@ -181,14 +108,24 @@ export async function fire(mthd, endp, pathParams, opt) {
181
108
  }
182
109
  }
183
110
  catch (e) {
184
- // @ts-ignore actualy endp is string
111
+ // @ts-expect-error actualy endp is string
185
112
  throw new ESIRequesError(`message: ${e.message}, endpoint=${endp}`);
186
113
  }
187
114
  }
115
+ // It should complete correctly.
116
+ /**
117
+ * @param {TESIRequestFunctionSignature<ESIRequestOptions>} fn
118
+ */
119
+ async function getEVEStatus(fn) {
120
+ const sdeVersion = await getSDEVersion();
121
+ log(`sdeVersion: ${sdeVersion}`.blue);
122
+ await fireRequestsDoesNotRequireAuth(fn);
123
+ return fn("get", "/status/");
124
+ }
188
125
  // type following and run
189
126
  // node v2.mjs
190
- // or yarn test:v2
191
- getEVEStatus().then(eveStatus => console.log(eveStatus));
127
+ // or yarn test
128
+ getEVEStatus(fire).then(eveStatus => console.log(eveStatus));
192
129
  // {
193
130
  // "players": 16503,
194
131
  // "server_version": "2794925",