eve-esi-types 3.2.6 → 3.2.7
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/CHANGELOG.md +13 -0
- package/README.md +87 -63
- package/dist/v2/esi-tagged-types.d.ts +77 -44
- package/dist/v2/experimental-esi-types.d.ts +114 -25
- package/dist/v2/index.d.ts +283 -197
- package/dist/v2/response-map.d.ts +1 -1
- package/dist/v2/types-index.d.ts +1 -1
- package/dist/v2/types-util.d.ts +126 -16
- package/dist/v2/util.d.ts +65 -3
- package/lib/console-util.mjs +1 -1
- package/lib/request-api.mjs +10 -11
- package/lib/rq-util.d.mts +72 -17
- package/lib/rq-util.mjs +106 -46
- package/minimal-rq.mjs +2 -2
- package/package.json +3 -3
- package/request-v3.mjs +8 -12
- package/tagged-rq.mjs +3 -2
- /package/{jsconfig.json → tsconfig.json} +0 -0
package/lib/rq-util.mjs
CHANGED
|
@@ -27,7 +27,11 @@ let LOG = false;
|
|
|
27
27
|
*/
|
|
28
28
|
export const BASE = "https://esi.evetech.net";
|
|
29
29
|
/**
|
|
30
|
-
* @
|
|
30
|
+
* @import * as ESIUtil from "./rq-util.mjs";
|
|
31
|
+
* @typedef {ESIUtil.Truthy} Truthy
|
|
32
|
+
* @typedef {ESIUtil.TAccessToken} TAccessToken
|
|
33
|
+
* @typedef {ESIUtil.TJWTPayload} TJWTPayload
|
|
34
|
+
* @typedef {ESIUtil.ESIRequestOptions} ESIRequestOptions
|
|
31
35
|
*/
|
|
32
36
|
/**
|
|
33
37
|
* simple named error class.
|
|
@@ -45,20 +49,18 @@ export class ESIErrorLimitReachedError extends ESIRequestError {
|
|
|
45
49
|
return 420;
|
|
46
50
|
}
|
|
47
51
|
}
|
|
48
|
-
/**
|
|
49
|
-
* @typedef {import("./rq-util.mjs").ESIRequestOptions} ESIRequestOptions
|
|
50
|
-
*/
|
|
51
52
|
// - - - - - - - - - - - - - - - - - - - -
|
|
52
53
|
// utility functions
|
|
53
54
|
// - - - - - - - - - - - - - - - - - - - -
|
|
54
55
|
/**
|
|
55
56
|
* @template T
|
|
57
|
+
* @template {Record<string, unknown>} O
|
|
56
58
|
* @param {[T] | [(T | undefined)?]} opt
|
|
57
|
-
* @returns {NonNullable<T>}
|
|
59
|
+
* @returns {NonNullable<T> & O}
|
|
58
60
|
*/
|
|
59
61
|
export const normalizeOptions = (opt) => {
|
|
60
62
|
//* ctt
|
|
61
|
-
return /** @type {NonNullable<T>} */ (opt.length ? (opt[0] ?? {}) : {});
|
|
63
|
+
return /** @type {NonNullable<T> & O} */ (opt.length ? (opt[0] ?? {}) : {});
|
|
62
64
|
/*/
|
|
63
65
|
const r = /** @type {NonNullable<T>} * /(opt.length ? (opt[0] ?? {}): {}) as NonNullable<T>;
|
|
64
66
|
log(`normalizeOptions::[${JSON.stringify(r)}]`);
|
|
@@ -74,30 +76,33 @@ export const normalizeOptions = (opt) => {
|
|
|
74
76
|
* @param {string} endpointUrl
|
|
75
77
|
* @param {RequestInit} requestOpt
|
|
76
78
|
* @param {URLSearchParams} urlParams
|
|
77
|
-
* @param {(minus?: Truthy) => void=}
|
|
79
|
+
* @param {(minus?: Truthy) => void=} progress
|
|
80
|
+
* @param {true=} allowFetchPages 2025/4/26
|
|
78
81
|
* @returns {Promise<any>}
|
|
79
82
|
*/
|
|
80
|
-
export const handleSuccessResponse = async (response, endpointUrl, requestOpt, urlParams,
|
|
83
|
+
export const handleSuccessResponse = async (response, endpointUrl, requestOpt, urlParams, progress = () => { }, allowFetchPages) => {
|
|
81
84
|
// NoContentResponse
|
|
82
85
|
if (response.status === 204)
|
|
83
86
|
return {};
|
|
84
87
|
/** @type {any} */
|
|
85
88
|
const data = await response.json();
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
89
|
+
if (allowFetchPages) {
|
|
90
|
+
// - - - - x-pages response.
|
|
91
|
+
// +undefined is NaN
|
|
92
|
+
// @ts-expect-error becouse +null is 0
|
|
93
|
+
const pc = +response.headers.get("x-pages");
|
|
94
|
+
// has remaining pages? NaN > 1 === false !isNaN(pageCount)
|
|
95
|
+
if (pc > 1) {
|
|
96
|
+
LOG && log('found "x-pages" header, pages: %d', pc);
|
|
97
|
+
const remData = await fetchP(endpointUrl, requestOpt, urlParams, pc, progress);
|
|
98
|
+
// finally, decide product data.
|
|
99
|
+
if (isArray(data) && isArray(remData)) {
|
|
100
|
+
// DEVNOTE: 2019/7/23 15:01:48 - types
|
|
101
|
+
return data.concat(remData);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
remData && Object.assign(data, remData);
|
|
105
|
+
}
|
|
101
106
|
}
|
|
102
107
|
}
|
|
103
108
|
return data;
|
|
@@ -228,6 +233,9 @@ export const initOptions = (method, opt) => {
|
|
|
228
233
|
qss[key] = oqs[key];
|
|
229
234
|
}
|
|
230
235
|
if (opt.auth) {
|
|
236
|
+
if (!opt.token) {
|
|
237
|
+
throw new Error("Authentication required: missing `token`");
|
|
238
|
+
}
|
|
231
239
|
// @ts-ignore The header is indeed an object
|
|
232
240
|
rqopt.headers.authorization = `Bearer ${opt.token}`;
|
|
233
241
|
}
|
|
@@ -247,19 +255,19 @@ export const initOptions = (method, opt) => {
|
|
|
247
255
|
* @param {RequestInit} rqopt request options
|
|
248
256
|
* @param {URLSearchParams} usp queries
|
|
249
257
|
* @param {number} pc pageCount
|
|
250
|
-
* @param {(minus?: number) => void=}
|
|
258
|
+
* @param {(minus?: number) => void=} progress
|
|
251
259
|
* @returns {Promise<T | null>}
|
|
252
260
|
*/
|
|
253
|
-
export const fetchP = async (endpointUrl, rqopt, usp, pc,
|
|
261
|
+
export const fetchP = async (endpointUrl, rqopt, usp, pc, progress = () => { }) => {
|
|
254
262
|
const rqs = [];
|
|
255
263
|
for (let i = 2; i <= pc;) {
|
|
256
264
|
usp.set("page", (i++) + "");
|
|
257
|
-
|
|
265
|
+
progress();
|
|
258
266
|
rqs.push(fetch(`${endpointUrl}?${usp + ""}`, rqopt).then(res => res.json()).catch(reason => {
|
|
259
267
|
console.warn(reason);
|
|
260
268
|
return [];
|
|
261
269
|
}).finally(() => {
|
|
262
|
-
|
|
270
|
+
progress(1);
|
|
263
271
|
}));
|
|
264
272
|
}
|
|
265
273
|
return Promise.all(rqs).then(jsons => {
|
|
@@ -276,7 +284,10 @@ export const fetchP = async (endpointUrl, rqopt, usp, pc, increment = () => { })
|
|
|
276
284
|
return null;
|
|
277
285
|
});
|
|
278
286
|
};
|
|
287
|
+
const CBT_RE = /{\w+}/g;
|
|
279
288
|
/** ### replace (C)urly (B)races (T)oken
|
|
289
|
+
*
|
|
290
|
+
* + Replace each `{…}` placeholder in the endpoint string with the corresponding ID.
|
|
280
291
|
*
|
|
281
292
|
* @example
|
|
282
293
|
* "/characters/{character_id}/skills"
|
|
@@ -284,24 +295,51 @@ export const fetchP = async (endpointUrl, rqopt, usp, pc, increment = () => { })
|
|
|
284
295
|
* "/characters/<char.character_id>/skills"
|
|
285
296
|
*
|
|
286
297
|
* @template {unknown} T
|
|
287
|
-
* @param {T} endpoint e.g
|
|
288
|
-
* @param {number[]} ids
|
|
289
|
-
* @returns {T}
|
|
298
|
+
* @param {T} endpoint An endpoint template, e.g. "/characters/{character_id}/skills"
|
|
299
|
+
* @param {number[]} ids An array of numbers to fill into each placeholder, in order of appearance
|
|
300
|
+
* @returns {T} A fully-qualified endpoint string with all `{…}` tokens replaced by their IDs
|
|
290
301
|
*/
|
|
291
302
|
export const replaceCbt = (endpoint, ids) => {
|
|
292
303
|
let idx = 0;
|
|
293
|
-
|
|
294
|
-
return endpoint.replace(/{([\w]+)}/g, () => ids[idx++] + "");
|
|
304
|
+
return /** @type {T} */ (/** @type {string} */ (endpoint).replace(CBT_RE, () => String(ids[idx++])));
|
|
295
305
|
};
|
|
296
306
|
/**
|
|
297
307
|
* @template {unknown} T
|
|
298
|
-
* @param {T}
|
|
308
|
+
* @param {T} endpoint this means endpoint url fragment like `/characters/{character_id}/` or `/characters/{character_id}/agents_research/`
|
|
299
309
|
* + The version parameter is forced to apply `latest`
|
|
300
310
|
* @returns {string}
|
|
301
311
|
*/
|
|
302
|
-
export const curl = (
|
|
303
|
-
|
|
304
|
-
|
|
312
|
+
export const curl = (endpoint) => {
|
|
313
|
+
return `${BASE}/latest/${/** @type {string} */ (endpoint).replace(/^\/+|\/+$/g, "")}/`;
|
|
314
|
+
};
|
|
315
|
+
/**
|
|
316
|
+
* Type guard that checks whether the given object has a `pathParams` property
|
|
317
|
+
* of type `number` or `number[]`.
|
|
318
|
+
*
|
|
319
|
+
* @template {Record<string, unknown>} T - The type of the object being checked.
|
|
320
|
+
* @param {T} opt - The object to inspect.
|
|
321
|
+
* @returns {opt is (T & { pathParams: number | number[] })}
|
|
322
|
+
* `true` if `opt` contains a `pathParams` property whose value is either
|
|
323
|
+
* a single number or an array of numbers, otherwise `false`.
|
|
324
|
+
*
|
|
325
|
+
* @date 2025/4/28
|
|
326
|
+
*/
|
|
327
|
+
export function hasPathParams(opt) {
|
|
328
|
+
if (typeof opt !== "object" || opt === null)
|
|
329
|
+
return false;
|
|
330
|
+
return "pathParams" in opt && (typeof opt.pathParams === "number" || Array.isArray(opt.pathParams));
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
*
|
|
334
|
+
* @param {string} accessToken OAuth 2.0 access token
|
|
335
|
+
* @returns {TJWTPayload}
|
|
336
|
+
*/
|
|
337
|
+
export const getJWTPayload = (accessToken) => {
|
|
338
|
+
// const [header, payload, sig] = accessToken.split(".");
|
|
339
|
+
// const headerJson = a2b(header); maybe always {"alg":"RS256","kid":"JWT-Signature-Key","typ":"JWT"}
|
|
340
|
+
// const sigJson = a2b(sig);
|
|
341
|
+
const json = atob(accessToken.split(".")[1]);
|
|
342
|
+
return JSON.parse(json); // as NsEVEOAuth.TJWTPayload;
|
|
305
343
|
};
|
|
306
344
|
/**
|
|
307
345
|
* @date 2020/03/31
|
|
@@ -351,24 +389,43 @@ export function getLogger() {
|
|
|
351
389
|
*
|
|
352
390
|
* @type {TESIEnhancedRequestFunctionSignature<TPrependParams, ESIRequestOptions>}
|
|
353
391
|
*/
|
|
392
|
+
// @ts-ignore ts(2322) ignore on ts file, bad js file is OK?
|
|
354
393
|
const fireWithoutAuth = (fn, method, endpoint, ...opt) => {
|
|
355
394
|
const arg = opt.length ? opt[0] : void 0;
|
|
356
395
|
if (typeof fn === "function") {
|
|
357
|
-
|
|
396
|
+
// @ts-expect-error TODO: ts(2345) The argument type does not match the type of the specified parameter
|
|
397
|
+
return fn(method, endpoint, arg);
|
|
358
398
|
}
|
|
359
399
|
// @ts-expect-error TODO: ts(2345) The argument type does not match the type of the specified parameter
|
|
360
400
|
return fn[method](endpoint, arg);
|
|
361
401
|
};
|
|
362
|
-
|
|
402
|
+
// /**
|
|
403
|
+
// * ```
|
|
404
|
+
// * process.env.CID // Specify EVE Character id
|
|
405
|
+
// * process.env.OAUTH_TOKEN // Spedify valid OAuth token
|
|
406
|
+
// * ```
|
|
407
|
+
// * @param envName
|
|
408
|
+
// */
|
|
409
|
+
// const getEnvValue = (envName: string) => process.env[envName] ?? null;
|
|
410
|
+
/** @type {TAccessToken} */
|
|
411
|
+
const token = /** @type {TAccessToken} */ (process.env.OAUTH_TOKEN ?? "token.token.token");
|
|
412
|
+
const ID_SomeEVECharacter = (() => {
|
|
413
|
+
if (token !== "token.token.token") {
|
|
414
|
+
const payload = getJWTPayload(token);
|
|
415
|
+
return +payload.sub.split(":")[2];
|
|
416
|
+
}
|
|
417
|
+
return 9000;
|
|
418
|
+
})();
|
|
363
419
|
/**
|
|
364
420
|
* #### Fire a request that does not require authentication.
|
|
365
421
|
*
|
|
422
|
+
* + __CAVEAT:__ This function should only be used for testing.
|
|
423
|
+
*
|
|
366
424
|
* @param {TPrependParams} fn
|
|
367
425
|
* @returns {Promise<void>}
|
|
368
426
|
*/
|
|
369
427
|
export async function fireRequestsDoesNotRequireAuth(fn) {
|
|
370
428
|
const { clog, rlog } = getLogger();
|
|
371
|
-
const ID_SomeEVECharacter = 90000;
|
|
372
429
|
const ID_CCP_Zoetrope = 2112625428;
|
|
373
430
|
try {
|
|
374
431
|
// - - - - - - - - - - - -
|
|
@@ -391,17 +448,21 @@ export async function fireRequestsDoesNotRequireAuth(fn) {
|
|
|
391
448
|
rlog("get:/incursions/".green);
|
|
392
449
|
await fireWithoutAuth(fn, "get", "/incursions/").then(log);
|
|
393
450
|
if (is("withError")) {
|
|
451
|
+
log(`Try character ${ID_SomeEVECharacter} assets request`);
|
|
394
452
|
await fireWithoutAuth(fn, "get", "/characters/{character_id}/assets/", {
|
|
395
|
-
auth: true,
|
|
453
|
+
auth: true, token,
|
|
396
454
|
pathParams: ID_SomeEVECharacter,
|
|
397
|
-
token
|
|
398
455
|
}).then(assets => {
|
|
399
456
|
log(assets.slice(0, 5));
|
|
400
457
|
});
|
|
401
|
-
|
|
458
|
+
log(`Try character ${ID_SomeEVECharacter} fittings request`);
|
|
459
|
+
await fireWithoutAuth(fn, "get", `/characters/${ID_SomeEVECharacter}/fittings/`, {
|
|
402
460
|
auth: true,
|
|
403
|
-
// pathParams: [
|
|
404
|
-
|
|
461
|
+
// pathParams: [ID_SomeEVECharacter, 56789], // ✅ At this point, the expected semantic error is successfully triggered as intended.
|
|
462
|
+
token
|
|
463
|
+
}).then(fittings => {
|
|
464
|
+
log(fittings.slice(0, 5));
|
|
465
|
+
});
|
|
405
466
|
}
|
|
406
467
|
}
|
|
407
468
|
// - - - - - - - - - - - -
|
|
@@ -434,8 +495,7 @@ export async function fireRequestsDoesNotRequireAuth(fn) {
|
|
|
434
495
|
// Authentication is required, so an error will occur.
|
|
435
496
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
436
497
|
let willFailed = await fireWithoutAuth(fn, "get", `/characters/${ID_SomeEVECharacter}/ship/`, {
|
|
437
|
-
auth: true,
|
|
438
|
-
token //: "token.token.token"
|
|
498
|
+
auth: true, token
|
|
439
499
|
});
|
|
440
500
|
log(`get:/characters/${ID_SomeEVECharacter}/ship/, returns:`, willFailed);
|
|
441
501
|
// in this case, "categories" and "search" is required
|
package/minimal-rq.mjs
CHANGED
|
@@ -29,8 +29,8 @@ const log = util.getUniversalLogger("[request-mini]: ");
|
|
|
29
29
|
const esiMethods = /** @type {TESIRequestFunctionMethods2} */ ({});
|
|
30
30
|
/** @satisfies {TESIEntryMethod[]} */ (["get", "post", "put", "delete"]).forEach((method) => {
|
|
31
31
|
esiMethods[method] = /** @type {TESIRequestFunctionEachMethod2<typeof method, util.ESIRequestOptions>} */ ((endpoint, opt) => {
|
|
32
|
-
// @ts-expect
|
|
33
|
-
return request2(method, endpoint,
|
|
32
|
+
// @ts-expect-error ts(2345)
|
|
33
|
+
return request2(method, endpoint, opt);
|
|
34
34
|
});
|
|
35
35
|
});
|
|
36
36
|
// It should complete correctly.
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eve-esi-types",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.7",
|
|
4
4
|
"description": "Extracted the main type of ESI. use for ESI request response types (version 2 only)",
|
|
5
5
|
"main": "dist/v2/index.d.ts",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"start": "tsc
|
|
7
|
+
"start": "tsc",
|
|
8
8
|
"test": "node request-v3.mjs -debug",
|
|
9
9
|
"test:mini": "node minimal-rq.mjs -debug"
|
|
10
10
|
},
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"LICENSE",
|
|
22
22
|
"*.md",
|
|
23
23
|
"package.json",
|
|
24
|
-
"
|
|
24
|
+
"tsconfig.json"
|
|
25
25
|
],
|
|
26
26
|
"keywords": [
|
|
27
27
|
"api",
|
package/request-v3.mjs
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// - - - - - - - - - - - - - - - - - - - -
|
|
14
14
|
// imports
|
|
15
15
|
// - - - - - - - - - - - - - - - - - - - -
|
|
16
|
-
import { is, curl, replaceCbt, getSDEVersion, normalizeOptions, initOptions, isDebug, fireRequestsDoesNotRequireAuth, isSuccess, handleESIError, handleSuccessResponse, } from "./lib/rq-util.mjs";
|
|
16
|
+
import { is, curl, replaceCbt, hasPathParams, getSDEVersion, normalizeOptions, initOptions, isDebug, fireRequestsDoesNotRequireAuth, isSuccess, handleESIError, handleSuccessResponse, } from "./lib/rq-util.mjs";
|
|
17
17
|
// - - - - - - - - - - - - - - - - - - - -
|
|
18
18
|
// constants, types
|
|
19
19
|
// - - - - - - - - - - - - - - - - - - - -
|
|
@@ -37,7 +37,7 @@ const LOG = isDebug();
|
|
|
37
37
|
*/
|
|
38
38
|
let ax = 0;
|
|
39
39
|
/** @type {function(Truthy=): number} */
|
|
40
|
-
const
|
|
40
|
+
const progress = (minus) => minus ? ax-- : ax++;
|
|
41
41
|
/**
|
|
42
42
|
* @returns Get The Current ESI request pending count.
|
|
43
43
|
*/
|
|
@@ -53,16 +53,12 @@ export const getRequestPending = () => ax;
|
|
|
53
53
|
*/
|
|
54
54
|
export const fire = /** @type {TESIRequestFunctionSignature2<ESIRequestOptions>} */ (async (mthd, endp, ...opt) => {
|
|
55
55
|
// When only options are provided
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (actualOpt.pathParams) {
|
|
60
|
-
pathParams = typeof actualOpt.pathParams === "number" ? [actualOpt.pathParams] : isArray(actualOpt.pathParams) ? actualOpt.pathParams : void 0;
|
|
61
|
-
}
|
|
62
|
-
if (isArray(pathParams)) {
|
|
56
|
+
const nOpt = normalizeOptions(opt);
|
|
57
|
+
if (hasPathParams(nOpt)) {
|
|
58
|
+
const pathParams = Array.isArray(nOpt.pathParams) ? nOpt.pathParams : [nOpt.pathParams];
|
|
63
59
|
endp = replaceCbt(endp, pathParams);
|
|
64
60
|
}
|
|
65
|
-
const { rqopt, qss } = initOptions(mthd,
|
|
61
|
+
const { rqopt, qss } = initOptions(mthd, nOpt);
|
|
66
62
|
const endpointUrl = curl(endp);
|
|
67
63
|
const up = new URLSearchParams(qss);
|
|
68
64
|
const url = `${endpointUrl}${up.size ? `?${up}` : ""}`;
|
|
@@ -72,11 +68,11 @@ export const fire = /** @type {TESIRequestFunctionSignature2<ESIRequestOptions>}
|
|
|
72
68
|
const res = await fetch(url, rqopt).finally(() => ax--);
|
|
73
69
|
// The parameters are different for successful and error responses.
|
|
74
70
|
if (isSuccess(res.status)) {
|
|
75
|
-
return handleSuccessResponse(res, endpointUrl, rqopt, up,
|
|
71
|
+
return handleSuccessResponse(res, endpointUrl, rqopt, up, progress);
|
|
76
72
|
}
|
|
77
73
|
// else if (isError(status)) {}
|
|
78
74
|
// Actually, throw Error
|
|
79
|
-
throw await handleESIError(res, endpointUrl,
|
|
75
|
+
throw await handleESIError(res, endpointUrl, nOpt.cancelable);
|
|
80
76
|
}
|
|
81
77
|
catch (e) {
|
|
82
78
|
throw e;
|
package/tagged-rq.mjs
CHANGED
|
@@ -42,8 +42,9 @@ if (util.is("withError")) {
|
|
|
42
42
|
esi.assets.get(`/characters/${ID_CCP_Zoetrope}/assets/`, {
|
|
43
43
|
auth: true
|
|
44
44
|
}).then(console.log).catch(console.log);
|
|
45
|
-
esi.mail.post(
|
|
45
|
+
esi.mail.post("/characters/{character_id}/mail/", ({
|
|
46
46
|
auth: true,
|
|
47
|
+
pathParams: ID_CCP_Zoetrope, // ✅ At this point, the expected semantic error is successfully triggered as intended.
|
|
47
48
|
body: {
|
|
48
49
|
subject: "test!!",
|
|
49
50
|
body: "",
|
|
@@ -52,7 +53,7 @@ if (util.is("withError")) {
|
|
|
52
53
|
}]
|
|
53
54
|
},
|
|
54
55
|
// token: "s.s.s"
|
|
55
|
-
})).then(console.log).catch(console.log);
|
|
56
|
+
}) /* satisfies Pick<TESIResponsePostEntry<"/characters/{character_id}/mail/">, "auth" | "body"> & { pathParams: number } */).then(console.log).catch(console.log);
|
|
56
57
|
esi.fittings.delete("/characters/1234/fittings/56789/", {
|
|
57
58
|
// pathParams: [1234, 56789], // ✅ At this point, the expected semantic error is successfully triggered as intended.
|
|
58
59
|
auth: true
|
|
File without changes
|