@naturalcycles/js-lib 15.45.0 → 15.46.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.
@@ -1,4 +1,5 @@
1
1
  import { _isBackendErrorResponseObject, _isErrorLike, _isErrorObject } from '../error/error.util.js'
2
+ import type { ErrorLike } from '../error/index.js'
2
3
  import type { Reviver } from '../types.js'
3
4
  import { _jsonParseIfPossible } from './json.util.js'
4
5
  import { _safeJsonStringify } from './safeJsonStringify.js'
@@ -101,65 +102,27 @@ export function _stringify(obj: any, opt: StringifyOptions = {}): string {
101
102
  }
102
103
 
103
104
  if (obj instanceof Error || _isErrorLike(obj)) {
104
- const { includeErrorCause = true } = opt
105
- //
106
- // Error or ErrorLike
107
- //
108
-
109
- // Omit "default" error name as non-informative
110
- // UPD: no, it's still important to understand that we're dealing with Error and not just some string
111
- // if (obj?.name === 'Error') {
112
- // s = obj.message
113
- // }
114
- // if (_isErrorObject(obj) && _isHttpErrorObject(obj)) {
115
- // // Printing (0) to avoid ambiguity
116
- // s = `${obj.name}(${obj.data.backendResponseStatusCode}): ${obj.message}`
117
- // }
118
-
119
- s = [obj.name, obj.message].filter(Boolean).join(': ')
120
-
121
- if (typeof (obj as any).code === 'string') {
122
- // Error that has no `data`, but has `code` property
123
- s += `\ncode: ${(obj as any).code}`
124
- }
125
-
126
- if (opt.includeErrorData && _isErrorObject(obj) && Object.keys(obj.data).length) {
127
- s += '\n' + _stringify(obj.data, opt)
128
- }
129
-
130
- if (opt.includeErrorStack && obj.stack) {
131
- // Here we're using the previously-generated "title line" (e.g "Error: some_message"),
132
- // concatenating it with the Stack (but without the title line of the Stack)
133
- // This is to fix the rare error (happened with Got) where `err.message` was changed,
134
- // but err.stack had "old" err.message
135
- // This should "fix" that
136
- const sLines = s.split('\n').length
137
-
138
- s = [s, ...obj.stack.split('\n').slice(sLines)].join('\n')
139
- }
140
-
141
- if (supportsAggregateError && obj instanceof AggregateError && obj.errors.length) {
142
- s = [
143
- s,
144
- `${obj.errors.length} error(s):`,
145
- ...obj.errors.map((err, i) => `${i + 1}. ${_stringify(err, opt)}`),
146
- ].join('\n')
147
- }
148
-
149
- if (obj.cause && includeErrorCause) {
150
- s = s + '\nCaused by: ' + _stringify(obj.cause, opt)
151
- }
105
+ s = stringifyErrorLike(obj, opt)
152
106
  } else if (typeof obj === 'string') {
153
- //
154
- // String
155
- //
156
-
157
107
  s = obj.trim() || 'empty_string'
108
+ // todo: think about it more
109
+ // Stringifying it like a JSON would.
110
+ // To highlight that it's a String (and not a Number) - using double-quotes, JSON-like.
111
+ // s = `"${obj}"`
112
+ } else if (typeof obj === 'number') {
113
+ s = String(obj)
114
+ // todo: support RegExp and Date, when split between Browser and Node stringification is implemented
115
+ // } else if (obj instanceof RegExp) {
116
+ // s = String(obj)
117
+ // } else if (obj instanceof Date) {
118
+ // s = `Date (${obj.toISOString()})`
158
119
  } else {
159
120
  //
160
121
  // Other
161
122
  //
162
123
  if (obj instanceof Map) {
124
+ // todo: double-check it, maybe Node's inspect has good built-in stringification
125
+
163
126
  obj = Object.fromEntries(obj)
164
127
  } else if (obj instanceof Set) {
165
128
  obj = [...obj]
@@ -189,3 +152,42 @@ export function _stringify(obj: any, opt: StringifyOptions = {}): string {
189
152
 
190
153
  return s
191
154
  }
155
+
156
+ function stringifyErrorLike(obj: Error | ErrorLike, opt: StringifyOptions): string {
157
+ const { includeErrorCause = true } = opt
158
+
159
+ let s = [obj.name, obj.message].filter(Boolean).join(': ')
160
+
161
+ if (typeof (obj as any).code === 'string') {
162
+ // Error that has no `data`, but has `code` property
163
+ s += `\ncode: ${(obj as any).code}`
164
+ }
165
+
166
+ if (opt.includeErrorData && _isErrorObject(obj) && Object.keys(obj.data).length) {
167
+ s += '\n' + _stringify(obj.data, opt)
168
+ }
169
+
170
+ if (opt.includeErrorStack && obj.stack) {
171
+ // Here we're using the previously-generated "title line" (e.g "Error: some_message"),
172
+ // concatenating it with the Stack (but without the title line of the Stack)
173
+ // This is to fix the rare error (happened with Got) where `err.message` was changed,
174
+ // but err.stack had "old" err.message
175
+ // This should "fix" that
176
+ const sLines = s.split('\n').length
177
+
178
+ s = [s, ...obj.stack.split('\n').slice(sLines)].join('\n')
179
+ }
180
+
181
+ if (supportsAggregateError && obj instanceof AggregateError && obj.errors.length) {
182
+ s = [
183
+ s,
184
+ `${obj.errors.length} error(s):`,
185
+ ...obj.errors.map((err, i) => `${i + 1}. ${_stringify(err, opt)}`),
186
+ ].join('\n')
187
+ }
188
+
189
+ if (obj.cause && includeErrorCause) {
190
+ s = s + '\nCaused by: ' + _stringify(obj.cause, opt)
191
+ }
192
+ return s
193
+ }