@naturalcycles/js-lib 15.44.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.
- package/dist/env.d.ts +6 -0
- package/dist/env.js +8 -0
- package/dist/object/keySortedMap.d.ts +18 -14
- package/dist/object/keySortedMap.js +74 -56
- package/dist/object/keySortedMap2.d.ts +72 -0
- package/dist/object/keySortedMap2.js +184 -0
- package/dist/object/map2.d.ts +1 -0
- package/dist/object/map2.js +3 -0
- package/dist/object/set2.d.ts +1 -1
- package/dist/object/set2.js +2 -2
- package/dist/string/stringify.js +45 -43
- package/dist/validation/validation.d.ts +2 -2
- package/dist/zod/zod.shared.schemas.d.ts +0 -2
- package/dist/zod/zod.shared.schemas.js +0 -4
- package/dist/zod/zod.util.d.ts +1 -1
- package/package.json +2 -2
- package/src/env.ts +9 -0
- package/src/json-schema/jsonSchemaBuilder.ts +0 -3
- package/src/object/keySortedMap.ts +84 -59
- package/src/object/keySortedMap2.ts +221 -0
- package/src/object/map2.ts +4 -0
- package/src/object/set2.ts +2 -2
- package/src/string/stringify.ts +54 -52
- package/src/validation/validation.ts +4 -4
- package/src/zod/zod.shared.schemas.ts +0 -5
- package/src/zod/zod.util.ts +1 -1
package/src/object/map2.ts
CHANGED
|
@@ -31,5 +31,9 @@ export class Map2<K = any, V = any> extends Map<K, V> {
|
|
|
31
31
|
return Object.fromEntries(this)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
override toString(): string {
|
|
35
|
+
return `Map2(${this.size}) ${JSON.stringify(Object.fromEntries(this))}`
|
|
36
|
+
}
|
|
37
|
+
|
|
34
38
|
// consider more helpful .toString() ?
|
|
35
39
|
}
|
package/src/object/set2.ts
CHANGED
|
@@ -41,8 +41,8 @@ export class Set2<T = any> extends Set<T> {
|
|
|
41
41
|
return [...this]
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
override
|
|
45
|
-
return
|
|
44
|
+
override toString(): string {
|
|
45
|
+
return `Set2(${this.size}) ${JSON.stringify([...this])}`
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// todo: consider more helpful .toString() ?
|
package/src/string/stringify.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
+
}
|
|
@@ -15,12 +15,12 @@ import type { AppError } from '../error/error.util.js'
|
|
|
15
15
|
*
|
|
16
16
|
* @experimental
|
|
17
17
|
*/
|
|
18
|
-
export type ValidationFunction<
|
|
19
|
-
input:
|
|
18
|
+
export type ValidationFunction<IN, OUT, ERR extends AppError> = (
|
|
19
|
+
input: IN,
|
|
20
20
|
opt?: ValidationFunctionOptions,
|
|
21
|
-
) => ValidationFunctionResult<
|
|
21
|
+
) => ValidationFunctionResult<OUT, ERR>
|
|
22
22
|
|
|
23
|
-
export type ValidationFunctionResult<
|
|
23
|
+
export type ValidationFunctionResult<OUT, ERR extends AppError> = [err: ERR | null, output: OUT]
|
|
24
24
|
|
|
25
25
|
export interface ValidationFunctionOptions {
|
|
26
26
|
/**
|
|
@@ -61,10 +61,6 @@ function isoDate(): ZodBrandedString<IsoDate> {
|
|
|
61
61
|
.describe('IsoDate') as ZodBrandedString<IsoDate>
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
function email(): z.ZodEmail {
|
|
65
|
-
return z.email().describe('Email')
|
|
66
|
-
}
|
|
67
|
-
|
|
68
64
|
const BASE62_REGEX = /^[a-zA-Z0-9]+$/
|
|
69
65
|
const BASE64_REGEX = /^[A-Za-z0-9+/]+={0,2}$/
|
|
70
66
|
const BASE64URL_REGEX = /^[\w\-/]+$/
|
|
@@ -131,7 +127,6 @@ export const customZodSchemas = {
|
|
|
131
127
|
base64,
|
|
132
128
|
base64Url,
|
|
133
129
|
dbEntity,
|
|
134
|
-
email,
|
|
135
130
|
ianaTimezone,
|
|
136
131
|
isoDate,
|
|
137
132
|
jwt,
|
package/src/zod/zod.util.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { ValidationFunction, ValidationFunctionResult } from '../validation
|
|
|
7
7
|
|
|
8
8
|
export function getZodValidationFunction<T>(
|
|
9
9
|
schema: ZodType<T>,
|
|
10
|
-
): ValidationFunction<T, ZodValidationError> {
|
|
10
|
+
): ValidationFunction<T, T, ZodValidationError> {
|
|
11
11
|
return (input, opt) => {
|
|
12
12
|
_assert(!opt?.mutateInput, 'mutateInput=true is not yet supported with Zod')
|
|
13
13
|
return zSafeValidate(input, schema)
|