@tvlabs/wdio-service 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -56,22 +56,22 @@ To use this with WebdriverIO remote but without the test runner, call the before
56
56
  import { remote } from 'webdriverio';
57
57
  import { TVLabsService } from '@tvlabs/wdio-service';
58
58
 
59
- const capabilities = { ... };
60
-
61
- const wdOpts = {
62
- capabilities,
63
- hostname: 'appium.tvlabs.ai',
64
- port: 4723,
65
- headers: {
66
- Authorization: `Bearer ${process.env.TVLABS_API_TOKEN}`,
67
- },
68
- };
69
-
70
- const serviceOpts = {
71
- apiKey: process.env.TVLABS_API_TOKEN,
72
- }
73
-
74
59
  async function run() {
60
+ const capabilities = { ... };
61
+
62
+ const wdOpts = {
63
+ capabilities,
64
+ hostname: 'appium.tvlabs.ai',
65
+ port: 4723,
66
+ headers: {
67
+ Authorization: `Bearer ${process.env.TVLABS_API_TOKEN}`,
68
+ },
69
+ };
70
+
71
+ const serviceOpts = {
72
+ apiKey: process.env.TVLABS_API_TOKEN,
73
+ }
74
+
75
75
  const service = new TVLabsService(serviceOpts, capabilities, {})
76
76
 
77
77
  // The TV Labs service does not use specs or a cid, pass default values.
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,kBAAkB,EAIlB,QAAQ,EACT,MAAM,YAAY,CAAC;AAGpB,qBAAa,aAAa;IAgBtB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,QAAQ;IAlBlB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAU;IAC/B,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAOZ;gBAGD,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,MAAM,EAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,QAAiB;IAgB/B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBxB,UAAU,CACd,YAAY,EAAE,kBAAkB,EAChC,UAAU,EAAE,MAAM,EAClB,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,CAAC;YAWJ,WAAW;YAkBX,cAAc;IAsD5B,OAAO,CAAC,gBAAgB;YAUV,cAAc;YAuBd,IAAI;YAgBJ,IAAI;IAoBlB,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,MAAM,CAAC,cAAc;CAU9B"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,kBAAkB,EAIlB,QAAQ,EACT,MAAM,YAAY,CAAC;AAGpB,qBAAa,aAAa;IAgBtB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,QAAQ;IAlBlB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAU;IAC/B,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAOZ;gBAGD,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,MAAM,EAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,QAAiB;IAgB/B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBxB,UAAU,CACd,YAAY,EAAE,kBAAkB,EAChC,UAAU,EAAE,MAAM,EAClB,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,CAAC;YAWJ,WAAW;YAkBX,cAAc;IAsD5B,OAAO,CAAC,gBAAgB;YAUV,cAAc;YAuBd,IAAI;YAgBJ,IAAI;IAoBlB,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,MAAM,CAAC,cAAc;CAQ9B"}
package/cjs/index.js CHANGED
@@ -50,9 +50,58 @@ class Logger {
50
50
  formatMessage(level, ...args) {
51
51
  const timestamp = new Date().toISOString();
52
52
  return `${timestamp} ${level.toUpperCase()} ${this.name}: ${args
53
- .map((arg) => typeof arg === 'object' ? JSON.stringify(arg) : String(arg))
53
+ .map((arg) => this.serializeArg(arg))
54
54
  .join(' ')}`;
55
55
  }
56
+ serializeArg(arg) {
57
+ if (typeof arg === 'string' ||
58
+ typeof arg === 'number' ||
59
+ typeof arg === 'boolean') {
60
+ return String(arg);
61
+ }
62
+ if (arg === null || arg === undefined) {
63
+ return String(arg);
64
+ }
65
+ if (arg instanceof Error) {
66
+ return arg.stack || `${arg.name}: ${arg.message}`;
67
+ }
68
+ if (typeof arg === 'object') {
69
+ try {
70
+ const stringified = JSON.stringify(arg, (key, value) => {
71
+ if (value instanceof Error) {
72
+ return `${value.name}: ${value.message}`;
73
+ }
74
+ return value;
75
+ });
76
+ if (stringified === '{}') {
77
+ const keys = Object.getOwnPropertyNames(arg);
78
+ if (keys.length > 0) {
79
+ const props = {};
80
+ keys.forEach((key) => {
81
+ try {
82
+ const value = arg[key];
83
+ if (value instanceof Error) {
84
+ props[key] = `${value.name}: ${value.message}`;
85
+ }
86
+ else {
87
+ props[key] = value;
88
+ }
89
+ }
90
+ catch {
91
+ props[key] = '[unable to access]';
92
+ }
93
+ });
94
+ return JSON.stringify(props);
95
+ }
96
+ }
97
+ return stringified;
98
+ }
99
+ catch {
100
+ return String(arg);
101
+ }
102
+ }
103
+ return String(arg);
104
+ }
56
105
  debug(...args) {
57
106
  if (this.shouldLog('debug')) {
58
107
  console.log(this.formatMessage('debug', ...args));
@@ -81,7 +130,7 @@ class Logger {
81
130
  }
82
131
 
83
132
  var name = "@tvlabs/wdio-service";
84
- var version = "0.1.4";
133
+ var version = "0.1.5";
85
134
  var packageJson = {
86
135
  name: name,
87
136
  version: version};
@@ -274,8 +323,7 @@ class TVLabsChannel {
274
323
  return `https://tvlabs.ai/app/sessions/${sessionId}`;
275
324
  }
276
325
  static logSocketError(log, event, _transport, _establishedConnections) {
277
- const error = event.error;
278
- log.error('Socket error:', error || event);
326
+ log.error('Socket error:', event.error);
279
327
  }
280
328
  }
281
329
 
package/cjs/logger.d.ts CHANGED
@@ -5,6 +5,7 @@ export declare class Logger {
5
5
  constructor(name: string, logLevel?: LogLevel);
6
6
  private shouldLog;
7
7
  private formatMessage;
8
+ private serializeArg;
8
9
  debug(...args: unknown[]): void;
9
10
  info(...args: unknown[]): void;
10
11
  warn(...args: unknown[]): void;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAc3C,qBAAa,MAAM;IAEf,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ;gBADR,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,QAAiB;IAGrC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,aAAa;IASrB,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAKhC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAc3C,qBAAa,MAAM;IAEf,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ;gBADR,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,QAAiB;IAGrC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,YAAY;IA2DpB,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAKhC"}
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,kBAAkB,EAIlB,QAAQ,EACT,MAAM,YAAY,CAAC;AAGpB,qBAAa,aAAa;IAgBtB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,QAAQ;IAlBlB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAU;IAC/B,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAOZ;gBAGD,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,MAAM,EAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,QAAiB;IAgB/B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBxB,UAAU,CACd,YAAY,EAAE,kBAAkB,EAChC,UAAU,EAAE,MAAM,EAClB,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,CAAC;YAWJ,WAAW;YAkBX,cAAc;IAsD5B,OAAO,CAAC,gBAAgB;YAUV,cAAc;YAuBd,IAAI;YAgBJ,IAAI;IAoBlB,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,MAAM,CAAC,cAAc;CAU9B"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,kBAAkB,EAIlB,QAAQ,EACT,MAAM,YAAY,CAAC;AAGpB,qBAAa,aAAa;IAgBtB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,QAAQ;IAlBlB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAU;IAC/B,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAOZ;gBAGD,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,MAAM,EAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,QAAiB;IAgB/B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBxB,UAAU,CACd,YAAY,EAAE,kBAAkB,EAChC,UAAU,EAAE,MAAM,EAClB,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,CAAC;YAWJ,WAAW;YAkBX,cAAc;IAsD5B,OAAO,CAAC,gBAAgB;YAUV,cAAc;YAuBd,IAAI;YAgBJ,IAAI;IAoBlB,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,MAAM,CAAC,cAAc;CAQ9B"}
package/esm/index.js CHANGED
@@ -27,9 +27,58 @@ class Logger {
27
27
  formatMessage(level, ...args) {
28
28
  const timestamp = new Date().toISOString();
29
29
  return `${timestamp} ${level.toUpperCase()} ${this.name}: ${args
30
- .map((arg) => typeof arg === 'object' ? JSON.stringify(arg) : String(arg))
30
+ .map((arg) => this.serializeArg(arg))
31
31
  .join(' ')}`;
32
32
  }
33
+ serializeArg(arg) {
34
+ if (typeof arg === 'string' ||
35
+ typeof arg === 'number' ||
36
+ typeof arg === 'boolean') {
37
+ return String(arg);
38
+ }
39
+ if (arg === null || arg === undefined) {
40
+ return String(arg);
41
+ }
42
+ if (arg instanceof Error) {
43
+ return arg.stack || `${arg.name}: ${arg.message}`;
44
+ }
45
+ if (typeof arg === 'object') {
46
+ try {
47
+ const stringified = JSON.stringify(arg, (key, value) => {
48
+ if (value instanceof Error) {
49
+ return `${value.name}: ${value.message}`;
50
+ }
51
+ return value;
52
+ });
53
+ if (stringified === '{}') {
54
+ const keys = Object.getOwnPropertyNames(arg);
55
+ if (keys.length > 0) {
56
+ const props = {};
57
+ keys.forEach((key) => {
58
+ try {
59
+ const value = arg[key];
60
+ if (value instanceof Error) {
61
+ props[key] = `${value.name}: ${value.message}`;
62
+ }
63
+ else {
64
+ props[key] = value;
65
+ }
66
+ }
67
+ catch {
68
+ props[key] = '[unable to access]';
69
+ }
70
+ });
71
+ return JSON.stringify(props);
72
+ }
73
+ }
74
+ return stringified;
75
+ }
76
+ catch {
77
+ return String(arg);
78
+ }
79
+ }
80
+ return String(arg);
81
+ }
33
82
  debug(...args) {
34
83
  if (this.shouldLog('debug')) {
35
84
  console.log(this.formatMessage('debug', ...args));
@@ -58,7 +107,7 @@ class Logger {
58
107
  }
59
108
 
60
109
  var name = "@tvlabs/wdio-service";
61
- var version = "0.1.4";
110
+ var version = "0.1.5";
62
111
  var packageJson = {
63
112
  name: name,
64
113
  version: version};
@@ -251,8 +300,7 @@ class TVLabsChannel {
251
300
  return `https://tvlabs.ai/app/sessions/${sessionId}`;
252
301
  }
253
302
  static logSocketError(log, event, _transport, _establishedConnections) {
254
- const error = event.error;
255
- log.error('Socket error:', error || event);
303
+ log.error('Socket error:', event.error);
256
304
  }
257
305
  }
258
306
 
package/esm/logger.d.ts CHANGED
@@ -5,6 +5,7 @@ export declare class Logger {
5
5
  constructor(name: string, logLevel?: LogLevel);
6
6
  private shouldLog;
7
7
  private formatMessage;
8
+ private serializeArg;
8
9
  debug(...args: unknown[]): void;
9
10
  info(...args: unknown[]): void;
10
11
  warn(...args: unknown[]): void;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAc3C,qBAAa,MAAM;IAEf,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ;gBADR,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,QAAiB;IAGrC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,aAAa;IASrB,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAKhC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAc3C,qBAAa,MAAM;IAEf,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ;gBADR,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,QAAiB;IAGrC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,YAAY;IA2DpB,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAKhC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tvlabs/wdio-service",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "WebdriverIO service that provides a better integration into TV Labs",
5
5
  "author": "Regan Karlewicz <regan@tvlabs.ai>",
6
6
  "license": "Apache-2.0",
@@ -46,11 +46,11 @@
46
46
  "@rollup/plugin-json": "^6.1.0",
47
47
  "@rollup/plugin-node-resolve": "^16.0.1",
48
48
  "@rollup/plugin-typescript": "^12.1.4",
49
- "@types/node": "^22.13.10",
49
+ "@types/node": "^24.1.0",
50
50
  "@types/phoenix": "^1.6.6",
51
51
  "@types/ws": "^8.18.0",
52
- "@typescript-eslint/eslint-plugin": "^8.36.0",
53
- "@typescript-eslint/parser": "^8.36.0",
52
+ "@typescript-eslint/eslint-plugin": "^8.38.0",
53
+ "@typescript-eslint/parser": "^8.38.0",
54
54
  "@vitest/coverage-v8": "^3.0.9",
55
55
  "@wdio/globals": "^9.12.1",
56
56
  "@wdio/types": "^9.10.1",
@@ -60,7 +60,7 @@
60
60
  "prettier": "^3.5.3",
61
61
  "rollup": "^4.45.1",
62
62
  "typescript": "^5.8.2",
63
- "typescript-eslint": "^8.36.0",
63
+ "typescript-eslint": "^8.38.0",
64
64
  "vitest": "^3.0.9",
65
65
  "webdriverio": "^9.12.1"
66
66
  },
package/src/channel.ts CHANGED
@@ -266,8 +266,6 @@ export class TVLabsChannel {
266
266
  _transport: new (endpoint: string) => object,
267
267
  _establishedConnections: number,
268
268
  ) {
269
- const error = event.error;
270
-
271
- log.error('Socket error:', error || event);
269
+ log.error('Socket error:', event.error);
272
270
  }
273
271
  }
package/src/logger.ts CHANGED
@@ -28,12 +28,69 @@ export class Logger {
28
28
  private formatMessage(level: LogLevel, ...args: unknown[]): string {
29
29
  const timestamp = new Date().toISOString();
30
30
  return `${timestamp} ${level.toUpperCase()} ${this.name}: ${args
31
- .map((arg) =>
32
- typeof arg === 'object' ? JSON.stringify(arg) : String(arg),
33
- )
31
+ .map((arg) => this.serializeArg(arg))
34
32
  .join(' ')}`;
35
33
  }
36
34
 
35
+ private serializeArg(arg: unknown): string {
36
+ if (
37
+ typeof arg === 'string' ||
38
+ typeof arg === 'number' ||
39
+ typeof arg === 'boolean'
40
+ ) {
41
+ return String(arg);
42
+ }
43
+
44
+ if (arg === null || arg === undefined) {
45
+ return String(arg);
46
+ }
47
+
48
+ if (arg instanceof Error) {
49
+ // Handle Error objects specially - use stack trace which includes name and message
50
+ return arg.stack || `${arg.name}: ${arg.message}`;
51
+ }
52
+
53
+ if (typeof arg === 'object') {
54
+ try {
55
+ // Try JSON.stringify with a custom replacer to handle nested Error objects
56
+ const stringified = JSON.stringify(arg, (key, value) => {
57
+ if (value instanceof Error) {
58
+ return `${value.name}: ${value.message}`;
59
+ }
60
+ return value;
61
+ });
62
+
63
+ // If it's just an empty object, try to extract more info
64
+ if (stringified === '{}') {
65
+ // For objects that don't serialize well, try to extract key properties
66
+ const keys = Object.getOwnPropertyNames(arg);
67
+ if (keys.length > 0) {
68
+ const props: Record<string, unknown> = {};
69
+ keys.forEach((key) => {
70
+ try {
71
+ const value = (arg as Record<string, unknown>)[key];
72
+ if (value instanceof Error) {
73
+ props[key] = `${value.name}: ${value.message}`;
74
+ } else {
75
+ props[key] = value;
76
+ }
77
+ } catch {
78
+ props[key] = '[unable to access]';
79
+ }
80
+ });
81
+ return JSON.stringify(props);
82
+ }
83
+ }
84
+ return stringified;
85
+ } catch {
86
+ // Fallback to string representation if JSON.stringify fails
87
+ return String(arg);
88
+ }
89
+ }
90
+
91
+ return String(arg);
92
+ }
93
+
37
94
  debug(...args: unknown[]): void {
38
95
  if (this.shouldLog('debug')) {
39
96
  console.log(this.formatMessage('debug', ...args));