@chainfuse/helpers 3.0.2 → 3.1.0

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.
@@ -17,25 +17,22 @@ 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 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;
20
+ static disordRestLogging(): Promise<z.ZodDefault<z.ZodObject<{
21
+ level: z.ZodDefault<z.ZodNumber>;
22
+ error: z.ZodDefault<z.ZodNumber>;
28
23
  color: z.ZodDefault<z.ZodBoolean>;
29
24
  custom: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnion<[z.ZodVoid, z.ZodPromise<z.ZodVoid>]>>>;
30
25
  }, "strip", z.ZodTypeAny, {
31
26
  level: number;
27
+ error: number;
32
28
  color: boolean;
33
29
  custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
34
30
  }, {
35
- level: number;
36
- custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
31
+ level?: number | undefined;
32
+ error?: number | undefined;
37
33
  color?: boolean | undefined;
38
- }>]>>>;
34
+ custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
35
+ }>>>;
39
36
  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>;
40
37
  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;
41
38
  static guildIcon(guildId: bigint | string, iconHash: Parameters<CDN['icon']>[1], options?: Parameters<CDN['icon']>[2]): string;
package/dist/discord.mjs CHANGED
@@ -30,23 +30,17 @@ export class DiscordHelpers {
30
30
  }
31
31
  static disordRestLogging() {
32
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
- }));
33
+ .object({
34
+ level: z.coerce.number().int().min(0).max(4).default(0),
35
+ error: z.coerce.number().int().min(0).max(4).default(1),
36
+ color: z.boolean().default(true),
37
+ custom: z
38
+ .function()
39
+ .args()
40
+ .returns(z.union([z.void(), z.promise(z.void())]))
41
+ .optional(),
42
+ })
43
+ .default({}));
50
44
  }
51
45
  static discordRest(apiKey, logging, cacheTtl = 24 * 60 * 60, forceCache = false, executionContext, restOptions) {
52
46
  return Promise.all([import('@discordjs/rest'), import('./crypto.mjs').then(({ CryptoHelpers }) => CryptoHelpers.base62secret(8))]).then(([{ REST }, potentialId]) => new REST({
@@ -68,8 +62,9 @@ export class DiscordHelpers {
68
62
  logging: {
69
63
  // discordRest has a different log level 2
70
64
  level: logging.level >= 2 ? logging.level - 1 : logging.level,
65
+ error: logging.error >= 2 ? logging.error - 1 : logging.error,
71
66
  ...('color' in logging && { color: logging.color }),
72
- ...(logging.level > 0 && {
67
+ ...((logging.level > 0 || logging.error > 0) && {
73
68
  custom: async (...args) => {
74
69
  const [, id, , url] = args;
75
70
  const customUrl = new URL(url);
@@ -78,20 +73,35 @@ export class DiscordHelpers {
78
73
  return logging.custom(...args);
79
74
  }
80
75
  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)));
76
+ await Promise.all([import('strip-ansi'), import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([{ default: stripAnsi }, chalk, { Helpers }]) => {
77
+ if (logging.level > 0) {
78
+ console.info('Discord Rest',
79
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
80
+ ...args
81
+ // Convert date to ISO string
82
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
83
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
84
+ // Wrap id in brackets
85
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
86
+ .map((value) => (value === id ? chalk.rgb(...Helpers.uniqueIdColor(stripAnsi(id)))(`[${stripAnsi(id)}]`) : value))
87
+ // Strip out redundant parts of url
88
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
89
+ .map((value) => (value === url ? `${customUrl.pathname}${customUrl.search}${customUrl.hash}` : value)));
90
+ }
91
+ else if (logging.error > 0) {
92
+ console.error('Discord Rest',
93
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
94
+ ...args
95
+ // Convert date to ISO string
96
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
97
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
98
+ // Wrap id in brackets
99
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
100
+ .map((value) => (value === id ? chalk.rgb(...Helpers.uniqueIdColor(stripAnsi(id)))(`[${stripAnsi(id)}]`) : value))
101
+ // Strip out redundant parts of url
102
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
103
+ .map((value) => (value === url ? `${customUrl.pathname}${customUrl.search}${customUrl.hash}` : value)));
104
+ }
95
105
  });
96
106
  }
97
107
  },
@@ -116,8 +126,7 @@ export class DiscordHelpers {
116
126
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
117
127
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-HIT', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
118
128
  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 });
129
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
121
130
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
122
131
  loggingItems.splice(3, 1, chalk.green(loggingItems[3]));
123
132
  });
@@ -155,8 +164,7 @@ export class DiscordHelpers {
155
164
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
156
165
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-MISS', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
157
166
  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 });
167
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
160
168
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
161
169
  loggingItems.splice(3, 1, chalk.yellow(loggingItems[3]));
162
170
  });
@@ -194,8 +202,7 @@ export class DiscordHelpers {
194
202
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
195
203
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-PUT', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
196
204
  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 });
205
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
199
206
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
200
207
  loggingItems.splice(3, 1, chalk.blue(loggingItems[3]));
201
208
  });
@@ -223,8 +230,7 @@ export class DiscordHelpers {
223
230
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
224
231
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
225
232
  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 });
233
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
228
234
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
229
235
  loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
230
236
  });
@@ -256,8 +262,7 @@ export class DiscordHelpers {
256
262
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
257
263
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-PUT', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
258
264
  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 });
265
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
261
266
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
262
267
  loggingItems.splice(3, 1, chalk.blue(loggingItems[3]));
263
268
  });
@@ -285,8 +290,7 @@ export class DiscordHelpers {
285
290
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
286
291
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
287
292
  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 });
293
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
290
294
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
291
295
  loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
292
296
  });
@@ -320,8 +324,7 @@ export class DiscordHelpers {
320
324
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
321
325
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-PUT', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
322
326
  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 });
327
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
325
328
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
326
329
  loggingItems.splice(3, 1, chalk.blue(loggingItems[3]));
327
330
  });
@@ -349,8 +352,7 @@ export class DiscordHelpers {
349
352
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
350
353
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
351
354
  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 });
355
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
354
356
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
355
357
  loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
356
358
  });
@@ -382,8 +384,7 @@ export class DiscordHelpers {
382
384
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
383
385
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-PUT', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
384
386
  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
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
387
388
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
388
389
  loggingItems.splice(3, 1, chalk.blue(loggingItems[3]));
389
390
  });
@@ -411,8 +412,7 @@ export class DiscordHelpers {
411
412
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
412
413
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
413
414
  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 });
415
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
416
416
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
417
417
  loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
418
418
  });
@@ -447,8 +447,7 @@ export class DiscordHelpers {
447
447
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
448
448
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
449
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 });
450
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
452
451
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
453
452
  loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
454
453
  });
@@ -477,8 +476,7 @@ export class DiscordHelpers {
477
476
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
478
477
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, `CACHE-ERROR: ${error}`, `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
479
478
  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 });
479
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
482
480
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
483
481
  loggingItems.splice(3, 1, chalk.red(loggingItems[3]));
484
482
  });
@@ -508,8 +506,7 @@ export class DiscordHelpers {
508
506
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
509
507
  const loggingItems = [new Date(), potentialId, cacheKey?.method ?? Methods.GET, 'CACHE-IGNORE', `${customUrl.pathname}${customUrl.search}${customUrl.hash}`];
510
508
  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 });
509
+ await Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
513
510
  loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(potentialId))(loggingItems[1]));
514
511
  loggingItems.splice(3, 1, chalk.yellow(loggingItems[3]));
515
512
  });
package/dist/net.d.mts CHANGED
@@ -17,25 +17,22 @@ export declare enum Methods {
17
17
  'PATCH' = "PATCH"
18
18
  }
19
19
  export declare class NetHelpers {
20
- static cfApiLogging(): 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;
20
+ static cfApiLogging(): Promise<z.ZodDefault<z.ZodObject<{
21
+ level: z.ZodDefault<z.ZodNumber>;
22
+ error: z.ZodDefault<z.ZodNumber>;
28
23
  color: z.ZodDefault<z.ZodBoolean>;
29
24
  custom: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnion<[z.ZodVoid, z.ZodPromise<z.ZodVoid>]>>>;
30
25
  }, "strip", z.ZodTypeAny, {
31
26
  level: number;
27
+ error: number;
32
28
  color: boolean;
33
29
  custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
34
30
  }, {
35
- level: number;
36
- custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
31
+ level?: number | undefined;
32
+ error?: number | undefined;
37
33
  color?: boolean | undefined;
38
- }>]>>>;
34
+ custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
35
+ }>>>;
39
36
  /**
40
37
  * Creates an instance of the Cloudflare API client with enhanced logging capabilities.
41
38
  *
@@ -56,66 +53,58 @@ export declare class NetHelpers {
56
53
  */
57
54
  static cfApi(apiKey: string, logging?: z.input<Awaited<ReturnType<typeof NetHelpers.cfApiLogging>>>): Promise<import("cloudflare").Cloudflare>;
58
55
  static loggingFetchInit(): Promise<z.ZodObject<{
59
- logging: z.ZodDefault<z.ZodUnion<[z.ZodObject<{
60
- level: z.ZodLiteral<0>;
61
- }, "strip", z.ZodTypeAny, {
62
- level: 0;
63
- }, {
64
- level: 0;
65
- }>, z.ZodObject<{
66
- level: z.ZodNumber;
56
+ logging: z.ZodDefault<z.ZodObject<{
57
+ level: z.ZodDefault<z.ZodNumber>;
58
+ error: z.ZodDefault<z.ZodNumber>;
67
59
  color: z.ZodDefault<z.ZodBoolean>;
68
60
  custom: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnion<[z.ZodVoid, z.ZodPromise<z.ZodVoid>]>>>;
69
61
  }, "strip", z.ZodTypeAny, {
70
62
  level: number;
63
+ error: number;
71
64
  color: boolean;
72
65
  custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
73
66
  }, {
74
- level: number;
75
- custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
67
+ level?: number | undefined;
68
+ error?: number | undefined;
76
69
  color?: boolean | undefined;
77
- }>]>>;
70
+ custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
71
+ }>>;
78
72
  }, "strip", z.ZodTypeAny, {
79
73
  logging: {
80
- level: 0;
81
- } | {
82
74
  level: number;
75
+ error: number;
83
76
  color: boolean;
84
77
  custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
85
78
  };
86
79
  }, {
87
80
  logging?: {
88
- level: 0;
89
- } | {
90
- level: number;
91
- custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
81
+ level?: number | undefined;
82
+ error?: number | undefined;
92
83
  color?: boolean | undefined;
84
+ custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
93
85
  } | undefined;
94
86
  }>>;
95
- static loggingFetchInitLogging(): Promise<z.ZodDefault<z.ZodUnion<[z.ZodObject<{
96
- level: z.ZodLiteral<0>;
97
- }, "strip", z.ZodTypeAny, {
98
- level: 0;
99
- }, {
100
- level: 0;
101
- }>, z.ZodObject<{
102
- level: z.ZodNumber;
87
+ static loggingFetchInitLogging(): Promise<z.ZodDefault<z.ZodObject<{
88
+ level: z.ZodDefault<z.ZodNumber>;
89
+ error: z.ZodDefault<z.ZodNumber>;
103
90
  color: z.ZodDefault<z.ZodBoolean>;
104
91
  custom: z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnion<[z.ZodVoid, z.ZodPromise<z.ZodVoid>]>>>;
105
92
  }, "strip", z.ZodTypeAny, {
106
93
  level: number;
94
+ error: number;
107
95
  color: boolean;
108
96
  custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
109
97
  }, {
110
- level: number;
111
- custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
98
+ level?: number | undefined;
99
+ error?: number | undefined;
112
100
  color?: boolean | undefined;
113
- }>]>>>;
101
+ custom?: ((...args: unknown[]) => void | Promise<void>) | undefined;
102
+ }>>>;
114
103
  /**
115
104
  * A utility function that wraps the native `fetch` API with enhanced capabilities.
116
105
  * This function allows for customizable logging of request and response details, including headers, body, and status, with support for colorized output and custom logging handlers.
117
106
  *
118
- * @template RI - The type of the `RequestInit` object, defaulting to `RequestInit`. Intended for cloudflare's `RequestInit` variation.
107
+ * @template RI - The type of the `RequestInit` object, defaulting to `RequestInit`. Intended for Cloudflare's `RequestInit` variation.
119
108
  *
120
109
  * @param info - The input to the `fetch` function, which can be a `Request` object or a URL string.
121
110
  * @param init - An optional configuration object extending `RequestInit` with additional options.
@@ -127,8 +116,14 @@ export declare class NetHelpers {
127
116
  * - `level >= 2`: Logs request headers (with sensitive headers stripped).
128
117
  * - `level >= 3`: Logs request body (if available) and response body (if available).
129
118
  *
119
+ * ### Error Logging Levels:
120
+ * - `error >= 1`: Logs basic request details (timestamp, unique ID, method, and URL) only if an error occurs.
121
+ * - `error >= 2`: Logs request headers (with sensitive headers stripped) only if an error occurs.
122
+ * - `error >= 3`: Logs request body (if available) and response body (if available) only if an error occurs.
123
+ *
130
124
  * ### Logging Options:
131
125
  * - `logging.level`: The verbosity level of logging (1, 2, or 3).
126
+ * - `logging.error`: The verbosity level of error logging (1, 2, or 3).
132
127
  * - `logging.color`: A boolean indicating whether to use colorized output.
133
128
  * - `logging.custom`: An optional custom logging function to handle the log output.
134
129
  *
package/dist/net.mjs CHANGED
@@ -18,23 +18,17 @@ export var Methods;
18
18
  export class NetHelpers {
19
19
  static cfApiLogging() {
20
20
  return import('zod').then(({ z }) => z
21
- .union([
22
- z.object({
23
- level: z.literal(0),
24
- }),
25
- z.object({
26
- level: z.coerce.number().int().min(1).max(3),
27
- color: z.boolean().default(true),
28
- custom: z
29
- .function()
30
- .args()
31
- .returns(z.union([z.void(), z.promise(z.void())]))
32
- .optional(),
33
- }),
34
- ])
35
- .default({
36
- level: 0,
37
- }));
21
+ .object({
22
+ level: z.coerce.number().int().min(0).max(3).default(0),
23
+ error: z.coerce.number().int().min(0).max(3).default(1),
24
+ color: z.boolean().default(true),
25
+ custom: z
26
+ .function()
27
+ .args()
28
+ .returns(z.union([z.void(), z.promise(z.void())]))
29
+ .optional(),
30
+ })
31
+ .default({}));
38
32
  }
39
33
  /**
40
34
  * Creates an instance of the Cloudflare API client with enhanced logging capabilities.
@@ -61,84 +55,110 @@ export class NetHelpers {
61
55
  NetHelpers.cfApiLogging().then((parser) => parser.parseAsync(logging)),
62
56
  ]).then(([{ Cloudflare }, logging]) => new Cloudflare({
63
57
  apiToken: apiKey,
64
- fetch: async (info, init) => {
65
- const loggingFetchInit = {
66
- ...init,
67
- logging: {
68
- // Fake level 1 as 2 to get headers for ray-id
69
- level: logging.level === 1 ? 2 : logging.level,
70
- ...('color' in logging && { color: logging.color }),
71
- ...(logging.level > 0 && {
72
- custom: async (...args) => {
73
- const [, id, , url, headers] = args;
74
- const customUrl = new URL(url);
75
- const customHeaders = new Headers(headers);
76
- if (customHeaders.has('cf-ray')) {
77
- args.splice(3, 0, customHeaders.get('cf-ray'));
58
+ fetch: (info, init) => this.loggingFetch(info, {
59
+ ...init,
60
+ logging: {
61
+ // Fake level 1 as 2 to get headers for ray-id
62
+ level: logging.level === 1 ? 2 : logging.level,
63
+ error: logging.error === 1 ? 2 : logging.error,
64
+ ...('color' in logging && { color: logging.color }),
65
+ ...((logging.level > 0 || logging.error > 0) && {
66
+ custom: async (...args) => {
67
+ const [, id, , url, headers] = args;
68
+ const customUrl = new URL(url);
69
+ const customHeaders = new Headers(headers);
70
+ if (customHeaders.has('cf-ray')) {
71
+ args.splice(3, 0, customHeaders.get('cf-ray'));
72
+ }
73
+ if ('color' in logging && logging.color) {
74
+ await import('chalk')
75
+ .then(({ Chalk }) => {
76
+ const chalk = new Chalk({ level: 2 });
77
+ if (customHeaders.has('cf-ray')) {
78
+ args.splice(3, 1, chalk.rgb(255, 102, 51)(customHeaders.get('cf-ray')));
79
+ }
80
+ })
81
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
82
+ .catch(() => { });
83
+ }
84
+ if ('custom' in logging && logging.custom) {
85
+ // We faked level 1 as 2 to get headers for ray-id
86
+ if (logging.level === 1 || logging.error === 1) {
87
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
88
+ return logging.custom(...args.slice(0, -1));
78
89
  }
79
- if ('color' in logging && logging.color) {
80
- await import('chalk')
81
- .then(({ Chalk }) => {
82
- const chalk = new Chalk({ level: 2 });
83
- if (customHeaders.has('cf-ray')) {
84
- args.splice(3, 1, chalk.rgb(255, 102, 51)(customHeaders.get('cf-ray')));
85
- }
86
- })
87
- // eslint-disable-next-line @typescript-eslint/no-empty-function
88
- .catch(() => { });
90
+ else {
91
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
92
+ return logging.custom(...args);
89
93
  }
90
- if ('custom' in logging && logging.custom) {
94
+ }
95
+ else {
96
+ await Promise.all([import('strip-ansi'), import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([{ default: stripAnsi }, chalk, { Helpers }]) => {
91
97
  // We faked level 1 as 2 to get headers for ray-id
92
98
  if (logging.level === 1) {
99
+ console.info('CF Rest',
93
100
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
94
- return logging.custom(...args.slice(0, -1));
101
+ ...args
102
+ .slice(0, -1)
103
+ // Convert date to ISO string
104
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
105
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
106
+ // Wrap id in brackets
107
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
108
+ .map((value) => (value === id ? chalk.rgb(...Helpers.uniqueIdColor(stripAnsi(id)))(`[${stripAnsi(id)}]`) : value))
109
+ // Strip out redundant parts of url
110
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
111
+ .map((value) => (value === url ? `${customUrl.pathname}${customUrl.search}${customUrl.hash}` : value)));
95
112
  }
96
- else {
113
+ else if (logging.error === 1) {
114
+ console.error('CF Rest',
97
115
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
98
- return logging.custom(...args);
116
+ ...args
117
+ .slice(0, -1)
118
+ // Convert date to ISO string
119
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
120
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
121
+ // Wrap id in brackets
122
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
123
+ .map((value) => (value === id ? chalk.rgb(...Helpers.uniqueIdColor(stripAnsi(id)))(`[${stripAnsi(id)}]`) : value))
124
+ // Strip out redundant parts of url
125
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
126
+ .map((value) => (value === url ? `${customUrl.pathname}${customUrl.search}${customUrl.hash}` : value)));
99
127
  }
100
- }
101
- else {
102
- await Promise.all([import('strip-ansi'), import('chalk'), import("./index.mjs")]).then(([{ default: stripAnsi }, { Chalk }, { Helpers }]) => {
103
- const chalk = new Chalk({ level: 2 });
104
- // We faked level 1 as 2 to get headers for ray-id
105
- if (logging.level === 1) {
106
- console.info('CF Rest',
107
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
108
- ...args
109
- .slice(0, -1)
110
- // Convert date to ISO string
111
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
112
- .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
113
- // Wrap id in brackets
114
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
115
- .map((value) => (value === id ? chalk.rgb(...Helpers.uniqueIdColor(stripAnsi(id)))(`[${stripAnsi(id)}]`) : value))
116
- // Strip out redundant parts of url
117
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
118
- .map((value) => (value === url ? `${customUrl.pathname}${customUrl.search}${customUrl.hash}` : value)));
119
- }
120
- else {
121
- console.info('CF Rest',
122
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
123
- ...args
124
- // Convert date to ISO string
125
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
126
- .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
127
- // Wrap id in brackets
128
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
129
- .map((value) => (value === id ? chalk.rgb(...Helpers.uniqueIdColor(stripAnsi(id)))(`[${stripAnsi(id)}]`) : value))
130
- // Strip out redundant parts of url
131
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
132
- .map((value) => (value === url ? `${customUrl.pathname}${customUrl.search}${customUrl.hash}` : value)));
133
- }
134
- });
135
- }
136
- },
137
- }),
138
- },
139
- };
140
- return this.loggingFetch(info, loggingFetchInit);
141
- },
128
+ else if (logging.level > 0) {
129
+ console.info('CF Rest',
130
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
131
+ ...args
132
+ // Convert date to ISO string
133
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
134
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
135
+ // Wrap id in brackets
136
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
137
+ .map((value) => (value === id ? chalk.rgb(...Helpers.uniqueIdColor(stripAnsi(id)))(`[${stripAnsi(id)}]`) : value))
138
+ // Strip out redundant parts of url
139
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
140
+ .map((value) => (value === url ? `${customUrl.pathname}${customUrl.search}${customUrl.hash}` : value)));
141
+ }
142
+ else if (logging.error > 0) {
143
+ console.error('CF Rest',
144
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
145
+ ...args
146
+ // Convert date to ISO string
147
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
148
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
149
+ // Wrap id in brackets
150
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
151
+ .map((value) => (value === id ? chalk.rgb(...Helpers.uniqueIdColor(stripAnsi(id)))(`[${stripAnsi(id)}]`) : value))
152
+ // Strip out redundant parts of url
153
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
154
+ .map((value) => (value === url ? `${customUrl.pathname}${customUrl.search}${customUrl.hash}` : value)));
155
+ }
156
+ });
157
+ }
158
+ },
159
+ }),
160
+ },
161
+ }),
142
162
  }));
143
163
  }
144
164
  static loggingFetchInit() {
@@ -148,29 +168,22 @@ export class NetHelpers {
148
168
  }
149
169
  static loggingFetchInitLogging() {
150
170
  return import('zod').then(({ z }) => z
151
- .union([
152
- z.object({
153
- level: z.literal(0),
154
- }),
155
- z.object({
156
- level: z.coerce.number().int().min(1).max(3),
157
- color: z.boolean().default(true),
158
- custom: z
159
- .function()
160
- // .args()
161
- .returns(z.union([z.void(), z.promise(z.void())]))
162
- .optional(),
163
- }),
164
- ])
165
- .default({
166
- level: 0,
167
- }));
171
+ .object({
172
+ level: z.coerce.number().int().min(0).max(3).default(0),
173
+ error: z.coerce.number().int().min(0).max(3).default(1),
174
+ color: z.boolean().default(true),
175
+ custom: z
176
+ .function()
177
+ .returns(z.union([z.void(), z.promise(z.void())]))
178
+ .optional(),
179
+ })
180
+ .default({}));
168
181
  }
169
182
  /**
170
183
  * A utility function that wraps the native `fetch` API with enhanced capabilities.
171
184
  * This function allows for customizable logging of request and response details, including headers, body, and status, with support for colorized output and custom logging handlers.
172
185
  *
173
- * @template RI - The type of the `RequestInit` object, defaulting to `RequestInit`. Intended for cloudflare's `RequestInit` variation.
186
+ * @template RI - The type of the `RequestInit` object, defaulting to `RequestInit`. Intended for Cloudflare's `RequestInit` variation.
174
187
  *
175
188
  * @param info - The input to the `fetch` function, which can be a `Request` object or a URL string.
176
189
  * @param init - An optional configuration object extending `RequestInit` with additional options.
@@ -182,8 +195,14 @@ export class NetHelpers {
182
195
  * - `level >= 2`: Logs request headers (with sensitive headers stripped).
183
196
  * - `level >= 3`: Logs request body (if available) and response body (if available).
184
197
  *
198
+ * ### Error Logging Levels:
199
+ * - `error >= 1`: Logs basic request details (timestamp, unique ID, method, and URL) only if an error occurs.
200
+ * - `error >= 2`: Logs request headers (with sensitive headers stripped) only if an error occurs.
201
+ * - `error >= 3`: Logs request body (if available) and response body (if available) only if an error occurs.
202
+ *
185
203
  * ### Logging Options:
186
204
  * - `logging.level`: The verbosity level of logging (1, 2, or 3).
205
+ * - `logging.error`: The verbosity level of error logging (1, 2, or 3).
187
206
  * - `logging.color`: A boolean indicating whether to use colorized output.
188
207
  * - `logging.custom`: An optional custom logging function to handle the log output.
189
208
  *
@@ -195,104 +214,72 @@ export class NetHelpers {
195
214
  * - Provides hooks for custom logging implementations.
196
215
  */
197
216
  static loggingFetch(info, init) {
198
- return NetHelpers.loggingFetchInit()
199
- .then((parser) => parser.passthrough().parseAsync(init))
200
- .then((parsed) => parsed)
201
- .then((init) => import("./crypto.mjs")
202
- .then(({ CryptoHelpers }) => CryptoHelpers.base62secret(8))
203
- .then(async (id) => {
204
- if (init.logging.level) {
217
+ return Promise.all([
218
+ NetHelpers.loggingFetchInit()
219
+ .then((parser) => parser.passthrough().parseAsync(init))
220
+ .then((parsed) => parsed),
221
+ import("./crypto.mjs").then(({ CryptoHelpers }) => CryptoHelpers.base62secret(8)),
222
+ ]).then(async ([init, id]) => {
223
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
224
+ const requestErrorItems = [new Date(), id, init?.method ?? Methods.GET, this.isRequestLike(info) ? info.url : info.toString()];
225
+ if (init.logging.level || init.logging.error) {
205
226
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
206
- const loggingItems = [new Date(), id, init?.method ?? Methods.GET, this.isRequestLike(info) ? info.url : info.toString()];
227
+ const requestLoggingItems = [new Date(), id, init?.method ?? Methods.GET, this.isRequestLike(info) ? info.url : info.toString()];
207
228
  if (init.logging.level >= 2) {
208
- loggingItems.push(Object.fromEntries(this.stripSensitiveHeaders(new Headers(init?.headers)).entries()));
229
+ requestLoggingItems.push(Object.fromEntries(this.stripSensitiveHeaders(new Headers(init?.headers)).entries()));
230
+ }
231
+ if (init.logging.error >= 2) {
232
+ requestErrorItems.push(Object.fromEntries(this.stripSensitiveHeaders(new Headers(init?.headers)).entries()));
209
233
  }
210
234
  if (init.logging.level >= 3 && init?.body) {
211
235
  if (init.body instanceof ReadableStream) {
212
- loggingItems.push(Array.from(new Uint8Array(await new Response(init.body).arrayBuffer())));
236
+ requestLoggingItems.push(Array.from(new Uint8Array(await new Response(init.body).arrayBuffer())));
213
237
  }
214
238
  else if (new Headers(init.headers).get('Content-Type')?.toLowerCase().startsWith('application/json')) {
215
- loggingItems.push(JSON.parse(init.body));
239
+ requestLoggingItems.push(JSON.parse(init.body));
216
240
  }
217
241
  else {
218
- loggingItems.push(init.body);
242
+ requestLoggingItems.push(init.body);
219
243
  }
220
244
  }
221
- if ('color' in init.logging && init.logging.color) {
222
- await Promise.all([import('chalk'), import("./index.mjs")])
223
- .then(([{ Chalk }, { Helpers }]) => {
224
- const chalk = new Chalk({ level: 2 });
225
- loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(id))(id));
226
- })
227
- // eslint-disable-next-line @typescript-eslint/no-empty-function
228
- .catch(() => { });
229
- await this.methodColors(loggingItems[2])
230
- .then((color) => {
231
- if (color) {
232
- loggingItems.splice(2, 1, color(loggingItems[2]));
233
- }
234
- })
235
- // eslint-disable-next-line @typescript-eslint/no-empty-function
236
- .catch(() => { });
237
- }
238
- if ('custom' in init.logging && init.logging.custom) {
239
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
240
- await init.logging.custom(...loggingItems);
241
- }
242
- else {
243
- console.info(
244
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
245
- ...loggingItems
246
- // Convert date to ISO string
247
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
248
- .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
249
- // Wrap id in brackets
250
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
251
- .map((value) => (typeof value === 'string' && value.includes(id) ? value.replace(id, `[${id}]`) : value)));
252
- }
253
- }
254
- return id;
255
- })
256
- .then((id) =>
257
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
258
- new Promise((resolve, reject) => fetch(info, init)
259
- .then(async (response) => {
260
- if (init.logging.level) {
261
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
262
- const loggingItems = [new Date(), id, response.status, response.url];
263
- if (init.logging.level >= 2) {
264
- loggingItems.push(Object.fromEntries(this.stripSensitiveHeaders(response.headers).entries()));
265
- }
266
- if (init.logging.level >= 3 && init?.body) {
267
- const loggingClone = response.clone();
268
- if (response.headers.get('Content-Type')?.toLowerCase().startsWith('application/json')) {
269
- loggingItems.push(await loggingClone.json());
245
+ if (init.logging.error >= 3 && init?.body) {
246
+ if (init.body instanceof ReadableStream) {
247
+ requestErrorItems.push(Array.from(new Uint8Array(await new Response(init.body).arrayBuffer())));
248
+ }
249
+ else if (new Headers(init.headers).get('Content-Type')?.toLowerCase().startsWith('application/json')) {
250
+ requestErrorItems.push(JSON.parse(init.body));
270
251
  }
271
252
  else {
272
- loggingItems.push(await loggingClone.text());
253
+ requestErrorItems.push(init.body);
273
254
  }
274
- /**
275
- * @todo @demosjarco detect if the body is a stream and convert it to an array
276
- */
277
255
  }
278
256
  if ('color' in init.logging && init.logging.color) {
279
- await Promise.all([import('chalk'), import("./index.mjs")])
280
- .then(([{ Chalk }, { Helpers }]) => {
281
- const chalk = new Chalk({ level: 2 });
282
- loggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(id))(id));
283
- loggingItems.splice(2, 1, response.ok ? chalk.green(response.status) : chalk.red(response.status));
284
- })
257
+ await Promise.allSettled([
258
+ Promise.all([import('chalk').then(({ Chalk }) => new Chalk({ level: 2 })), import("./index.mjs")]).then(([chalk, { Helpers }]) => {
259
+ requestLoggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(id))(id));
260
+ requestErrorItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(id))(id));
261
+ }),
262
+ this.methodColors(requestLoggingItems[2]).then((color) => {
263
+ if (color) {
264
+ requestLoggingItems.splice(2, 1, color(requestLoggingItems[2]));
265
+ }
266
+ }),
267
+ this.methodColors(requestErrorItems[2]).then((color) => {
268
+ if (color) {
269
+ requestErrorItems.splice(2, 1, color(requestErrorItems[2]));
270
+ }
271
+ }),
285
272
  // eslint-disable-next-line @typescript-eslint/no-empty-function
286
- .catch(() => { });
273
+ ]).catch(() => { });
287
274
  }
288
- if ('custom' in init.logging && init.logging.custom) {
275
+ if (init.logging.level > 0 && 'custom' in init.logging && init.logging.custom) {
289
276
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
290
- await init.logging.custom(...loggingItems);
277
+ await init.logging.custom(...requestLoggingItems);
291
278
  }
292
- else {
279
+ else if (init.logging.level > 0) {
293
280
  console.info(
294
281
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
295
- ...loggingItems
282
+ ...requestLoggingItems
296
283
  // Convert date to ISO string
297
284
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
298
285
  .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
@@ -301,9 +288,104 @@ export class NetHelpers {
301
288
  .map((value) => (typeof value === 'string' && value.includes(id) ? value.replace(id, `[${id}]`) : value)));
302
289
  }
303
290
  }
304
- resolve(response);
305
- })
306
- .catch(reject))));
291
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
292
+ return new Promise((resolve, reject) => fetch(info, init)
293
+ .then(async (response) => {
294
+ if (init.logging.level || init.logging.error) {
295
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
296
+ const responseLoggingItems = [new Date(), id, response.status, response.url];
297
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
298
+ const responseErrorItems = [new Date(), id, response.status, response.url];
299
+ if (init.logging.level >= 2) {
300
+ responseLoggingItems.push(Object.fromEntries(this.stripSensitiveHeaders(response.headers).entries()));
301
+ }
302
+ if (init.logging.error >= 2) {
303
+ responseErrorItems.push(Object.fromEntries(this.stripSensitiveHeaders(response.headers).entries()));
304
+ }
305
+ if (init.logging.level >= 3 && init?.body) {
306
+ const loggingClone = response.clone();
307
+ if (response.headers.get('Content-Type')?.toLowerCase().startsWith('application/json')) {
308
+ responseLoggingItems.push(await loggingClone.json());
309
+ }
310
+ else {
311
+ responseLoggingItems.push(await loggingClone.text());
312
+ }
313
+ /**
314
+ * @todo @demosjarco detect if the body is a stream and convert it to an array
315
+ */
316
+ }
317
+ if (init.logging.error >= 3 && init?.body) {
318
+ const loggingClone = response.clone();
319
+ if (response.headers.get('Content-Type')?.toLowerCase().startsWith('application/json')) {
320
+ responseErrorItems.push(await loggingClone.json());
321
+ }
322
+ else {
323
+ responseErrorItems.push(await loggingClone.text());
324
+ }
325
+ /**
326
+ * @todo @demosjarco detect if the body is a stream and convert it to an array
327
+ */
328
+ }
329
+ if ('color' in init.logging && init.logging.color) {
330
+ await Promise.all([import('chalk'), import("./index.mjs")])
331
+ .then(([{ Chalk }, { Helpers }]) => {
332
+ const chalk = new Chalk({ level: 2 });
333
+ responseLoggingItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(id))(id));
334
+ responseLoggingItems.splice(2, 1, response.ok ? chalk.green(response.status) : chalk.red(response.status));
335
+ responseErrorItems.splice(1, 1, chalk.rgb(...Helpers.uniqueIdColor(id))(id));
336
+ responseErrorItems.splice(2, 1, response.ok ? chalk.green(response.status) : chalk.red(response.status));
337
+ })
338
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
339
+ .catch(() => { });
340
+ }
341
+ if (init.logging.level > 0 && 'custom' in init.logging && init.logging.custom) {
342
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
343
+ await init.logging.custom(...responseLoggingItems);
344
+ }
345
+ else if (init.logging.error > 0 && !response.ok && 'custom' in init.logging && init.logging.custom) {
346
+ // Send request errors too (since we barely now know if error or not)
347
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
348
+ await init.logging.custom(...requestErrorItems);
349
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
350
+ await init.logging.custom(...responseErrorItems);
351
+ }
352
+ else if (init.logging.level > 0) {
353
+ console.info(
354
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
355
+ ...responseLoggingItems
356
+ // Convert date to ISO string
357
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
358
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
359
+ // Wrap id in brackets
360
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
361
+ .map((value) => (typeof value === 'string' && value.includes(id) ? value.replace(id, `[${id}]`) : value)));
362
+ }
363
+ else if (init.logging.error > 0 && !response.ok) {
364
+ // Send request errors too (since we barely now know if error or not)
365
+ console.error(
366
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
367
+ ...requestErrorItems
368
+ // Convert date to ISO string
369
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
370
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
371
+ // Wrap id in brackets
372
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
373
+ .map((value) => (typeof value === 'string' && value.includes(id) ? value.replace(id, `[${id}]`) : value)));
374
+ console.error(
375
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
376
+ ...responseErrorItems
377
+ // Convert date to ISO string
378
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
379
+ .map((value) => (value instanceof Date && !isNaN(value.getTime()) ? value.toISOString() : value))
380
+ // Wrap id in brackets
381
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
382
+ .map((value) => (typeof value === 'string' && value.includes(id) ? value.replace(id, `[${id}]`) : value)));
383
+ }
384
+ }
385
+ resolve(response);
386
+ })
387
+ .catch(reject));
388
+ });
307
389
  }
308
390
  /**
309
391
  * Removes sensitive headers from the provided `Headers` object. Specifically, it deletes the `Set-Cookie` and `Authorization` headers.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chainfuse/helpers",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "",
5
5
  "author": "ChainFuse",
6
6
  "homepage": "https://github.com/ChainFuse/packages/tree/main/packages/helpers#readme",
@@ -56,9 +56,9 @@
56
56
  "zod": "^3.24.3"
57
57
  },
58
58
  "devDependencies": {
59
- "@chainfuse/types": "^2.10.3",
60
- "@cloudflare/workers-types": "^4.20250422.0",
59
+ "@chainfuse/types": "^2.10.4",
60
+ "@cloudflare/workers-types": "^4.20250423.0",
61
61
  "@types/node": "^22.14.1"
62
62
  },
63
- "gitHead": "98d1970d468f91261928a84b86f655ba30f15ccd"
63
+ "gitHead": "f9b0e6a8fb3f328c94929ca88590de730ffff860"
64
64
  }