@chainfuse/helpers 2.4.2 → 3.0.1

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.
@@ -1,6 +1,6 @@
1
- import type { CustomLoging } from '@chainfuse/types';
2
1
  import type { ExecutionContext } from '@cloudflare/workers-types/experimental';
3
- import { CDN, REST, type RESTOptions } from '@discordjs/rest';
2
+ import { CDN, type RESTOptions } from '@discordjs/rest';
3
+ import type { z } from 'zod';
4
4
  export declare class DiscordHelpers {
5
5
  /**
6
6
  * Discord Epoch, the first second of 2015 or 1420070400000
@@ -17,7 +17,26 @@ export declare class DiscordHelpers {
17
17
  * @link https://discord.com/developers/docs/reference#snowflakes-snowflake-id-format-structure-left-to-right
18
18
  */
19
19
  static discordSnowflakeToDate(snowflakeRaw?: bigint | string): Date;
20
- static discordRest(apiKey: string, cacheTtl?: number, forceCache?: boolean, executionContext?: ExecutionContext, logger?: CustomLoging, restOptions?: Partial<Omit<RESTOptions, 'agent' | 'authPrefix' | 'makeRequest'>>): REST;
20
+ static disordRestLogging(): Promise<z.ZodDefault<z.ZodUnion<[z.ZodObject<{
21
+ level: z.ZodLiteral<0>;
22
+ }, "strip", z.ZodTypeAny, {
23
+ level: 0;
24
+ }, {
25
+ level: 0;
26
+ }>, z.ZodObject<{
27
+ level: z.ZodNumber;
28
+ color: z.ZodDefault<z.ZodBoolean>;
29
+ custom: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnion<[z.ZodVoid, z.ZodPromise<z.ZodVoid>]>>>;
30
+ }, "strip", z.ZodTypeAny, {
31
+ level: number;
32
+ color: boolean;
33
+ custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
34
+ }, {
35
+ level: number;
36
+ custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
37
+ color?: boolean | undefined;
38
+ }>]>>>;
39
+ static discordRest(apiKey: string, logging: z.input<Awaited<ReturnType<typeof DiscordHelpers.disordRestLogging>>>, cacheTtl?: number, forceCache?: boolean, executionContext?: ExecutionContext, restOptions?: Partial<Omit<RESTOptions, 'agent' | 'authPrefix' | 'makeRequest'>>): Promise<import("@discordjs/rest").REST>;
21
40
  static userIcon(userId: bigint | string, userIconHash?: Parameters<CDN['avatar']>[1] | null, guildId?: bigint | string, memberIconHash?: Parameters<CDN['avatar']>[1] | null, options?: Parameters<CDN['avatar']>[2]): string;
22
41
  static guildIcon(guildId: bigint | string, iconHash: Parameters<CDN['icon']>[1], options?: Parameters<CDN['icon']>[2]): string;
23
42
  }
package/dist/discord.mjs CHANGED
@@ -1,6 +1,4 @@
1
- import { CDN, REST } from '@discordjs/rest';
2
- import { CryptoHelpers } from './crypto.mjs';
3
- import { NetHelpers } from './net.mjs';
1
+ import { CDN } from '@discordjs/rest';
4
2
  export class DiscordHelpers {
5
3
  /**
6
4
  * Discord Epoch, the first second of 2015 or 1420070400000
@@ -30,25 +28,82 @@ export class DiscordHelpers {
30
28
  const snowflake = BigInt(snowflakeRaw);
31
29
  return new Date(Number((snowflake >> BigInt(22)) + this.discordEpoch));
32
30
  }
33
- static discordRest(apiKey, cacheTtl = 24 * 60 * 60, forceCache = false, executionContext, logger = false, restOptions) {
34
- return new REST({
31
+ static disordRestLogging() {
32
+ return import('zod').then(({ z }) => z
33
+ .union([
34
+ z.object({
35
+ level: z.literal(0),
36
+ }),
37
+ z.object({
38
+ level: z.coerce.number().int().min(1).max(4),
39
+ color: z.boolean().default(true),
40
+ custom: z
41
+ .function()
42
+ .args()
43
+ .returns(z.union([z.void(), z.promise(z.void())]))
44
+ .optional(),
45
+ }),
46
+ ])
47
+ .default({
48
+ level: 0,
49
+ }));
50
+ }
51
+ static discordRest(apiKey, logging, cacheTtl = 24 * 60 * 60, forceCache = false, executionContext, restOptions) {
52
+ return Promise.all([import('@discordjs/rest'), import('./crypto.mjs').then(({ CryptoHelpers }) => CryptoHelpers.base62secret(8))]).then(([{ REST }, potentialId]) => new REST({
35
53
  ...restOptions,
36
54
  agent: null,
37
55
  authPrefix: 'Bot',
38
- makeRequest: (url, rawInit) => {
56
+ makeRequest: (url, rawInit) => Promise.all([
57
+ //
58
+ DiscordHelpers.disordRestLogging().then((parser) => parser.parseAsync(logging)),
59
+ import('./net.mjs'),
60
+ import('./crypto.mjs'),
61
+ ]).then(async ([logging, { NetHelpers, Methods }, { CryptoHelpers }]) => {
39
62
  // Extra safety to make sure the string really is a URL
40
63
  const info = new URL(url);
41
64
  // CF's implementation of `RequestInit` is functionally the same as w3c `RequestInit` but TS doesn't know that
42
65
  const init = rawInit;
66
+ const loggingFetchInit = {
67
+ ...init,
68
+ logging: {
69
+ // discordRest has a different log level 2
70
+ level: logging.level >= 2 ? logging.level - 1 : logging.level,
71
+ ...('color' in logging && { color: logging.color }),
72
+ ...(logging.level > 0 && {
73
+ custom: async (...args) => {
74
+ const [, id, , url] = args;
75
+ const customUrl = new URL(url);
76
+ if ('custom' in logging && logging.custom) {
77
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
78
+ return logging.custom(...args);
79
+ }
80
+ else {
81
+ await Promise.all([import('strip-ansi'), import('chalk'), import("./index.mjs")]).then(([{ default: stripAnsi }, { Chalk }, { Helpers }]) => {
82
+ const chalk = new Chalk({ level: 2 });
83
+ console.info('Discord Rest',
84
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
85
+ ...args
86
+ // Convert date to ISO string
87
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
88
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
89
+ // Wrap id in brackets
90
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
91
+ .map((value) => (value === id ? chalk.rgb(...Helpers.uniqueIdColor(stripAnsi(id)))(`[${stripAnsi(id)}]`) : value))
92
+ // Strip out redundant parts of url
93
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
94
+ .map((value) => (value === url ? `${customUrl.pathname}${customUrl.search}${customUrl.hash}` : value)));
95
+ });
96
+ }
97
+ },
98
+ }),
99
+ },
100
+ };
43
101
  const cacheKey = new Request(info, { ...init, headers: NetHelpers.stripSensitiveHeaders(new Headers(init.headers)) });
44
- if (logger) {
45
- console.debug('Discord Fetch request', cacheKey.url, JSON.stringify(NetHelpers.initBodyTrimmer({ ...init, headers: Object.fromEntries(NetHelpers.stripSensitiveHeaders(new Headers(init.headers)).entries()) }), null, '\t'));
46
- }
47
102
  /**
48
103
  * Only cache GET requests
49
104
  * Empty method means GET
50
105
  */
51
- if (cacheTtl && ((rawInit.method ?? 'GET').toLowerCase() === 'get' || forceCache)) {
106
+ if (caches && cacheTtl && ((rawInit.method ?? 'GET').toLowerCase() === 'get' || forceCache)) {
52
107
  // const cfCacheRef: Promise<Cache> | undefined = caches?.open('cfApi');
53
108
  const discordCacheRef = caches?.open(`discordApi`);
54
109
  return discordCacheRef
@@ -56,8 +111,32 @@ export class DiscordHelpers {
56
111
  .match(cacheKey)
57
112
  .then(async (cachedResponse) => {
58
113
  if (cachedResponse) {
59
- if (logger) {
60
- console.debug('Discord Cache hit', cacheKey.url);
114
+ if (logging.level >= 2) {
115
+ const customUrl = new URL(url);
116
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
117
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-HIT', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
118
+ if ('color' in logging && logging.color) {
119
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
120
+ const chalk = new Chalk({ level: 2 });
121
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
122
+ loggingItems.splice(3, 1, chalk.green(loggingItems[3]));
123
+ });
124
+ }
125
+ if ('custom' in logging && logging.custom) {
126
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
127
+ await logging.custom(...loggingItems);
128
+ }
129
+ else {
130
+ console.info(
131
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
132
+ ...loggingItems
133
+ // Convert date to ISO string
134
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
135
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
136
+ // Wrap id in brackets
137
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
138
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
139
+ }
61
140
  }
62
141
  // Clear out bad cache
63
142
  if (cachedResponse.status >= 500) {
@@ -71,10 +150,34 @@ export class DiscordHelpers {
71
150
  return cachedResponse;
72
151
  }
73
152
  else {
74
- if (logger) {
75
- console.warn('Discord Cache missed', cacheKey.url);
153
+ if (logging.level >= 2) {
154
+ const customUrl = new URL(url);
155
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
156
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-MISS', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
157
+ if ('color' in logging && logging.color) {
158
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
159
+ const chalk = new Chalk({ level: 2 });
160
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
161
+ loggingItems.splice(3, 1, chalk.yellow(loggingItems[3]));
162
+ });
163
+ }
164
+ if ('custom' in logging && logging.custom) {
165
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
166
+ await logging.custom(...loggingItems);
167
+ }
168
+ else {
169
+ console.info(
170
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
171
+ ...loggingItems
172
+ // Convert date to ISO string
173
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
174
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
175
+ // Wrap id in brackets
176
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
177
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
178
+ }
76
179
  }
77
- return NetHelpers.loggingFetch(info, init, undefined, logger).then(async (response) => {
180
+ return NetHelpers.loggingFetch(info, loggingFetchInit).then(async (response) => {
78
181
  if (response.ok) {
79
182
  response = new Response(response.body, {
80
183
  ...response,
@@ -85,28 +188,124 @@ export class DiscordHelpers {
85
188
  if (executionContext) {
86
189
  executionContext.waitUntil(discordCache
87
190
  .put(cacheKey, response.clone())
88
- .then(() => {
89
- if (logger) {
90
- console.debug('Discord Cache saved', 'with original etag', cacheKey.url);
191
+ .then(async () => {
192
+ if (logging.level >= 2) {
193
+ const customUrl = new URL(url);
194
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
195
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-PUT', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
196
+ if ('color' in logging && logging.color) {
197
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
198
+ const chalk = new Chalk({ level: 2 });
199
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
200
+ loggingItems.splice(3, 1, chalk.blue(loggingItems[3]));
201
+ });
202
+ }
203
+ if ('custom' in logging && logging.custom) {
204
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
205
+ await logging.custom(...loggingItems);
206
+ }
207
+ else {
208
+ console.info(
209
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
210
+ ...loggingItems
211
+ // Convert date to ISO string
212
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
213
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
214
+ // Wrap id in brackets
215
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
216
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
217
+ }
91
218
  }
92
219
  })
93
- .catch((error) => {
94
- if (logger) {
95
- console.error('Discord Cache put error', error);
220
+ .catch(async (error) => {
221
+ if (logging.level >= 2) {
222
+ const customUrl = new URL(url);
223
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
224
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
225
+ if ('color' in logging && logging.color) {
226
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
227
+ const chalk = new Chalk({ level: 2 });
228
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
229
+ loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
230
+ });
231
+ }
232
+ if ('custom' in logging && logging.custom) {
233
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
234
+ await logging.custom(...loggingItems);
235
+ }
236
+ else {
237
+ console.info(
238
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
239
+ ...loggingItems
240
+ // Convert date to ISO string
241
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
242
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
243
+ // Wrap id in brackets
244
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
245
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
246
+ }
96
247
  }
97
248
  }));
98
249
  }
99
250
  else {
100
251
  await discordCache
101
252
  .put(cacheKey, response.clone())
102
- .then(() => {
103
- if (logger) {
104
- console.debug('Discord Cache saved', 'with original etag', cacheKey.url);
253
+ .then(async () => {
254
+ if (logging.level >= 2) {
255
+ const customUrl = new URL(url);
256
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
257
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-PUT', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
258
+ if ('color' in logging && logging.color) {
259
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
260
+ const chalk = new Chalk({ level: 2 });
261
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
262
+ loggingItems.splice(3, 1, chalk.blue(loggingItems[3]));
263
+ });
264
+ }
265
+ if ('custom' in logging && logging.custom) {
266
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
267
+ await logging.custom(...loggingItems);
268
+ }
269
+ else {
270
+ console.info(
271
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
272
+ ...loggingItems
273
+ // Convert date to ISO string
274
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
275
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
276
+ // Wrap id in brackets
277
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
278
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
279
+ }
105
280
  }
106
281
  })
107
- .catch((error) => {
108
- if (logger) {
109
- console.error('Discord Cache put error', error);
282
+ .catch(async (error) => {
283
+ if (logging.level >= 2) {
284
+ const customUrl = new URL(url);
285
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
286
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
287
+ if ('color' in logging && logging.color) {
288
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
289
+ const chalk = new Chalk({ level: 2 });
290
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
291
+ loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
292
+ });
293
+ }
294
+ if ('custom' in logging && logging.custom) {
295
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
296
+ await logging.custom(...loggingItems);
297
+ }
298
+ else {
299
+ console.info(
300
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
301
+ ...loggingItems
302
+ // Convert date to ISO string
303
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
304
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
305
+ // Wrap id in brackets
306
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
307
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
308
+ }
110
309
  }
111
310
  });
112
311
  }
@@ -115,42 +314,124 @@ export class DiscordHelpers {
115
314
  if (executionContext) {
116
315
  executionContext.waitUntil(CryptoHelpers.generateETag(response)
117
316
  .then((etag) => response.headers.set('ETag', etag))
118
- .then(() => discordCache
119
- .put(cacheKey, response.clone())
120
- .then(() => {
121
- if (logger) {
122
- console.debug('Discord Cache saved', 'with generated etag', cacheKey.url);
123
- }
124
- })
125
- .catch((error) => {
126
- if (logger) {
127
- console.error('Discord Cache put error', error);
317
+ .then(() => discordCache.put(cacheKey, response.clone()).then(async () => {
318
+ if (logging.level >= 2) {
319
+ const customUrl = new URL(url);
320
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
321
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-PUT', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
322
+ if ('color' in logging && logging.color) {
323
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
324
+ const chalk = new Chalk({ level: 2 });
325
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
326
+ loggingItems.splice(3, 1, chalk.blue(loggingItems[3]));
327
+ });
328
+ }
329
+ if ('custom' in logging && logging.custom) {
330
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
331
+ await logging.custom(...loggingItems);
332
+ }
333
+ else {
334
+ console.info(
335
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
336
+ ...loggingItems
337
+ // Convert date to ISO string
338
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
339
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
340
+ // Wrap id in brackets
341
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
342
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
343
+ }
128
344
  }
129
345
  }))
130
- .catch((error) => {
131
- if (logger) {
132
- console.error('CryptoHelpers generateETag error', error);
346
+ .catch(async (error) => {
347
+ if (logging.level >= 2) {
348
+ const customUrl = new URL(url);
349
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
350
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
351
+ if ('color' in logging && logging.color) {
352
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
353
+ const chalk = new Chalk({ level: 2 });
354
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
355
+ loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
356
+ });
357
+ }
358
+ if ('custom' in logging && logging.custom) {
359
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
360
+ await logging.custom(...loggingItems);
361
+ }
362
+ else {
363
+ console.info(
364
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
365
+ ...loggingItems
366
+ // Convert date to ISO string
367
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
368
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
369
+ // Wrap id in brackets
370
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
371
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
372
+ }
133
373
  }
134
374
  }));
135
375
  }
136
376
  else {
137
377
  await CryptoHelpers.generateETag(response)
138
378
  .then((etag) => response.headers.set('ETag', etag))
139
- .then(() => discordCache
140
- .put(cacheKey, response.clone())
141
- .then(() => {
142
- if (logger) {
143
- console.debug('Discord Cache saved', 'with generated etag', cacheKey.url);
144
- }
145
- })
146
- .catch((error) => {
147
- if (logger) {
148
- console.error('Discord Cache put error', error);
379
+ .then(() => discordCache.put(cacheKey, response.clone()).then(async () => {
380
+ if (logging.level >= 2) {
381
+ const customUrl = new URL(url);
382
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
383
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-PUT', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
384
+ if ('color' in logging && logging.color) {
385
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
386
+ const chalk = new Chalk({ level: 2 });
387
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
388
+ loggingItems.splice(3, 1, chalk.blue(loggingItems[3]));
389
+ });
390
+ }
391
+ if ('custom' in logging && logging.custom) {
392
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
393
+ await logging.custom(...loggingItems);
394
+ }
395
+ else {
396
+ console.info(
397
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
398
+ ...loggingItems
399
+ // Convert date to ISO string
400
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
401
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
402
+ // Wrap id in brackets
403
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
404
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
405
+ }
149
406
  }
150
407
  }))
151
- .catch((error) => {
152
- if (logger) {
153
- console.error('CryptoHelpers generateETag error', error);
408
+ .catch(async (error) => {
409
+ if (logging.level >= 2) {
410
+ const customUrl = new URL(url);
411
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
412
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
413
+ if ('color' in logging && logging.color) {
414
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
415
+ const chalk = new Chalk({ level: 2 });
416
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
417
+ loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
418
+ });
419
+ }
420
+ if ('custom' in logging && logging.custom) {
421
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
422
+ await logging.custom(...loggingItems);
423
+ }
424
+ else {
425
+ console.info(
426
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
427
+ ...loggingItems
428
+ // Convert date to ISO string
429
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
430
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
431
+ // Wrap id in brackets
432
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
433
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
434
+ }
154
435
  }
155
436
  });
156
437
  }
@@ -160,27 +441,99 @@ export class DiscordHelpers {
160
441
  });
161
442
  }
162
443
  })
163
- .catch((error) => {
164
- if (logger) {
165
- console.error('Discord Cache match error', error);
444
+ .catch(async (error) => {
445
+ if (logging.level >= 2) {
446
+ const customUrl = new URL(url);
447
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
448
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
449
+ if ('color' in logging && logging.color) {
450
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
451
+ const chalk = new Chalk({ level: 2 });
452
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
453
+ loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
454
+ });
455
+ }
456
+ if ('custom' in logging && logging.custom) {
457
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
458
+ await logging.custom(...loggingItems);
459
+ }
460
+ else {
461
+ console.info(
462
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
463
+ ...loggingItems
464
+ // Convert date to ISO string
465
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
466
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
467
+ // Wrap id in brackets
468
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
469
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
470
+ }
166
471
  }
167
- return NetHelpers.loggingFetch(info, init, undefined, logger);
472
+ return NetHelpers.loggingFetch(info, loggingFetchInit);
168
473
  }))
169
- .catch((error) => {
170
- if (logger) {
171
- console.error('Discord Cache open error', error);
474
+ .catch(async (error) => {
475
+ if (logging.level >= 2) {
476
+ const customUrl = new URL(url);
477
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
478
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
479
+ if ('color' in logging && logging.color) {
480
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
481
+ const chalk = new Chalk({ level: 2 });
482
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
483
+ loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
484
+ });
485
+ }
486
+ if ('custom' in logging && logging.custom) {
487
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
488
+ await logging.custom(...loggingItems);
489
+ }
490
+ else {
491
+ console.info(
492
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
493
+ ...loggingItems
494
+ // Convert date to ISO string
495
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
496
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
497
+ // Wrap id in brackets
498
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
499
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
500
+ }
172
501
  }
173
- return NetHelpers.loggingFetch(info, init, undefined, logger);
502
+ return NetHelpers.loggingFetch(info, loggingFetchInit);
174
503
  });
175
504
  }
176
505
  else {
177
- if (logger) {
178
- console.warn('Discord Cache ignored', cacheKey.url);
506
+ if (logging.level >= 2) {
507
+ const customUrl = new URL(url);
508
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
509
+ const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-IGNORE', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
510
+ if ('color' in logging && logging.color) {
511
+ await Promise.all([import('chalk'), import("./index.mjs")]).then(([{ Chalk }, { Helpers }]) => {
512
+ const chalk = new Chalk({ level: 2 });
513
+ loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
514
+ loggingItems.splice(3, 1, chalk.yellow(loggingItems[3]));
515
+ });
516
+ }
517
+ if ('custom' in logging && logging.custom) {
518
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
519
+ await logging.custom(...loggingItems);
520
+ }
521
+ else {
522
+ console.info(
523
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
524
+ ...loggingItems
525
+ // Convert date to ISO string
526
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
527
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
528
+ // Wrap id in brackets
529
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
530
+ .map((value) => (typeof value === 'string' && value.includes(potentialId) ? value.replace(potentialId, `[${potentialId}]`) : value)));
531
+ }
179
532
  }
180
- return NetHelpers.loggingFetch(info, init, undefined, logger);
533
+ return NetHelpers.loggingFetch(info, loggingFetchInit);
181
534
  }
182
- },
183
- }).setToken(apiKey);
535
+ }),
536
+ }).setToken(apiKey));
184
537
  }
185
538
  static userIcon(userId, userIconHash, guildId, memberIconHash, options) {
186
539
  options = {