@naturalcycles/js-lib
Advanced tools
Comparing version 14.249.0 to 14.250.0
@@ -1,2 +0,2 @@ | ||
import { _isNotNullish } from '../is.util'; | ||
import { _assert } from '../error/assert'; | ||
import { END, } from '../types'; | ||
@@ -16,5 +16,7 @@ /** | ||
export function _chunk(array, size = 1) { | ||
return array.reduce((arr, item, idx) => { | ||
return idx % size === 0 ? [...arr, [item]] : [...arr.slice(0, -1), [...arr.slice(-1)[0], item]]; | ||
}, []); | ||
const a = []; | ||
for (let i = 0; i < array.length; i += size) { | ||
a.push(array.slice(i, i + size)); | ||
} | ||
return a; | ||
} | ||
@@ -80,12 +82,9 @@ /** | ||
export function _uniqBy(arr, mapper) { | ||
return [ | ||
...arr | ||
.reduce((map, item, index) => { | ||
const key = item === null || item === undefined ? item : mapper(item, index); | ||
if (!map.has(key)) | ||
map.set(key, item); | ||
return map; | ||
}, new Map()) | ||
.values(), | ||
]; | ||
const map = new Map(); | ||
for (const [i, item] of arr.entries()) { | ||
const key = item === undefined || item === null ? item : mapper(item, i); | ||
if (!map.has(key)) | ||
map.set(key, item); | ||
} | ||
return [...map.values()]; | ||
} | ||
@@ -133,9 +132,10 @@ /** | ||
export function _groupBy(items, mapper) { | ||
return items.reduce((map, item, index) => { | ||
const res = mapper(item, index); | ||
if (res !== undefined) { | ||
map[res] = [...(map[res] || []), item]; | ||
} | ||
return map; | ||
}, {}); | ||
const map = {}; | ||
for (const [i, item] of items.entries()) { | ||
const key = mapper(item, i); | ||
if (key === undefined) | ||
continue; | ||
(map[key] || (map[key] = [])).push(item); | ||
} | ||
return map; | ||
} | ||
@@ -288,3 +288,7 @@ /** | ||
export function _difference(source, ...diffs) { | ||
return diffs.reduce((a, b) => a.filter(c => !b.includes(c)), source); | ||
let a = source; | ||
for (const b of diffs) { | ||
a = a.filter(c => !b.includes(c)); | ||
} | ||
return a; | ||
} | ||
@@ -374,6 +378,11 @@ /** | ||
export function _minOrUndefined(array) { | ||
const a = array.filter(_isNotNullish); | ||
if (!a.length) | ||
return; | ||
return a.reduce((min, item) => (min <= item ? min : item)); | ||
let min; | ||
for (const item of array) { | ||
if (item === undefined || item === null) | ||
continue; | ||
if (min === undefined || item < min) { | ||
min = item; | ||
} | ||
} | ||
return min; | ||
} | ||
@@ -384,12 +393,16 @@ /** | ||
export function _min(array) { | ||
const a = array.filter(_isNotNullish); | ||
if (!a.length) | ||
throw new Error('_min called on empty array'); | ||
return a.reduce((min, item) => (min <= item ? min : item)); | ||
const min = _minOrUndefined(array); | ||
_assert(min !== undefined, '_min called on empty array'); | ||
return min; | ||
} | ||
export function _maxOrUndefined(array) { | ||
const a = array.filter(_isNotNullish); | ||
if (!a.length) | ||
return; | ||
return a.reduce((max, item) => (max >= item ? max : item)); | ||
let max; | ||
for (const item of array) { | ||
if (item === undefined || item === null) | ||
continue; | ||
if (max === undefined || item > max) { | ||
max = item; | ||
} | ||
} | ||
return max; | ||
} | ||
@@ -400,11 +413,9 @@ /** | ||
export function _max(array) { | ||
const a = array.filter(_isNotNullish); | ||
if (!a.length) | ||
throw new Error('_max called on empty array'); | ||
return a.reduce((max, item) => (max >= item ? max : item)); | ||
const max = _maxOrUndefined(array); | ||
_assert(max !== undefined, '_max called on empty array'); | ||
return max; | ||
} | ||
export function _maxBy(array, mapper) { | ||
const max = _maxByOrUndefined(array, mapper); | ||
if (max === undefined) | ||
throw new Error(`_maxBy returned undefined`); | ||
_assert(max !== undefined, '_maxBy returned undefined'); | ||
return max; | ||
@@ -414,4 +425,3 @@ } | ||
const min = _minByOrUndefined(array, mapper); | ||
if (min === undefined) | ||
throw new Error(`_minBy returned undefined`); | ||
_assert(min !== undefined, '_minBy returned undefined'); | ||
return min; | ||
@@ -418,0 +428,0 @@ } |
import { _assert } from '../error/assert'; | ||
import { _isTruthy } from '../is.util'; | ||
import { Iterable2 } from '../iter/iterable2'; | ||
@@ -495,3 +494,3 @@ import { localTime } from './localTime'; | ||
if (input instanceof Date) | ||
return !isNaN(input.getDate()); | ||
return !Number.isNaN(input.getDate()); | ||
return this.isValidString(input); | ||
@@ -516,3 +515,3 @@ } | ||
if (input instanceof Date) { | ||
if (isNaN(input.getDate())) | ||
if (Number.isNaN(input.getDate())) | ||
return; | ||
@@ -575,3 +574,3 @@ return new LocalDate(input.getFullYear(), input.getMonth() + 1, input.getDate()); | ||
fromDate(d) { | ||
_assert(!isNaN(d.getDate()), `localDate.fromDate is called on Date object that is invalid`); | ||
_assert(!Number.isNaN(d.getDate()), 'localDate.fromDate is called on Date object that is invalid'); | ||
return new LocalDate(d.getFullYear(), d.getMonth() + 1, d.getDate()); | ||
@@ -584,3 +583,3 @@ } | ||
fromDateInUTC(d) { | ||
_assert(!isNaN(d.getDate()), `localDate.fromDateInUTC is called on Date object that is invalid`); | ||
_assert(!Number.isNaN(d.getDate()), 'localDate.fromDateInUTC is called on Date object that is invalid'); | ||
return new LocalDate(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate()); | ||
@@ -603,3 +602,12 @@ } | ||
minOrUndefined(items) { | ||
return items.length ? this.min(items) : undefined; | ||
let min; | ||
for (const item of items) { | ||
if (!item) | ||
continue; | ||
const ld = this.fromInput(item); | ||
if (!min || ld.isBefore(min)) { | ||
min = ld; | ||
} | ||
} | ||
return min; | ||
} | ||
@@ -611,7 +619,5 @@ /** | ||
min(items) { | ||
const items2 = items.filter(_isTruthy); | ||
_assert(items2.length, 'localDate.min called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item)); | ||
const min = this.minOrUndefined(items); | ||
_assert(min, 'localDate.min called on empty array'); | ||
return min; | ||
} | ||
@@ -622,3 +628,12 @@ /** | ||
maxOrUndefined(items) { | ||
return items.length ? this.max(items) : undefined; | ||
let max; | ||
for (const item of items) { | ||
if (!item) | ||
continue; | ||
const ld = this.fromInput(item); | ||
if (!max || ld.isAfter(max)) { | ||
max = ld; | ||
} | ||
} | ||
return max; | ||
} | ||
@@ -630,7 +645,5 @@ /** | ||
max(items) { | ||
const items2 = items.filter(_isTruthy); | ||
_assert(items2.length, 'localDate.max called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item)); | ||
const max = this.maxOrUndefined(items); | ||
_assert(max, 'localDate.max called on empty array'); | ||
return max; | ||
} | ||
@@ -637,0 +650,0 @@ /** |
import { _assert } from '../error/assert'; | ||
import { _isTruthy } from '../is.util'; | ||
import { _ms } from '../time/time.util'; | ||
@@ -676,3 +675,3 @@ import { localDate } from './localDate'; | ||
if (input instanceof Date) | ||
return !isNaN(input.getDate()); | ||
return !Number.isNaN(input.getDate()); | ||
// We currently don't validate Unixtimestamp input, treat it as always valid | ||
@@ -698,3 +697,3 @@ if (typeof input === 'number') | ||
if (input instanceof Date) { | ||
if (isNaN(input.getDate())) | ||
if (Number.isNaN(input.getDate())) | ||
return; | ||
@@ -763,3 +762,3 @@ return new LocalTime(input); | ||
const d = new Date(s); | ||
return isNaN(d.getDate()) ? undefined : d; | ||
return Number.isNaN(d.getDate()) ? undefined : d; | ||
} | ||
@@ -792,3 +791,3 @@ const o = { | ||
fromDate(date) { | ||
_assert(!isNaN(date.getDate()), `localTime.fromDate is called on Date object that is invalid`); | ||
_assert(!Number.isNaN(date.getDate()), 'localTime.fromDate is called on Date object that is invalid'); | ||
return new LocalTime(date); | ||
@@ -848,20 +847,34 @@ } | ||
minOrUndefined(items) { | ||
return items.length ? this.min(items) : undefined; | ||
let min; | ||
for (const item of items) { | ||
if (!item) | ||
continue; | ||
const lt = this.fromInput(item); | ||
if (!min || lt.$date.valueOf() < min.$date.valueOf()) { | ||
min = lt; | ||
} | ||
} | ||
return min; | ||
} | ||
min(items) { | ||
const items2 = items.filter(_isTruthy); | ||
_assert(items2.length, 'localTime.min called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item)); | ||
const min = this.minOrUndefined(items); | ||
_assert(min, 'localTime.min called on empty array'); | ||
return min; | ||
} | ||
maxOrUndefined(items) { | ||
return items.length ? this.max(items) : undefined; | ||
let max; | ||
for (const item of items) { | ||
if (!item) | ||
continue; | ||
const lt = this.fromInput(item); | ||
if (!max || lt.$date.valueOf() > max.$date.valueOf()) { | ||
max = lt; | ||
} | ||
} | ||
return max; | ||
} | ||
max(items) { | ||
const items2 = items.filter(_isTruthy); | ||
_assert(items2.length, 'localTime.max called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item)); | ||
const max = this.maxOrUndefined(items); | ||
_assert(max, 'localTime.max called on empty array'); | ||
return max; | ||
} | ||
@@ -902,3 +915,3 @@ } | ||
} | ||
else if (date.getTime() >= startOfThisYear.getTime()) { | ||
if (date.getTime() >= startOfThisYear.getTime()) { | ||
return year; | ||
@@ -905,0 +918,0 @@ } |
@@ -52,3 +52,3 @@ import { _deepEquals, _isErrorObject, _stringify, AssertionError } from '..'; | ||
const msg = message || | ||
[`not deeply equal`, `expected: ${_stringify(expected)}`, `got : ${_stringify(actual)}`] | ||
['not deeply equal', `expected: ${_stringify(expected)}`, `got : ${_stringify(actual)}`] | ||
.filter(Boolean) | ||
@@ -89,2 +89,3 @@ .join('\n'); | ||
export function _assertTypeOf(v, expectedType, message) { | ||
// biome-ignore lint/suspicious/useValidTypeof: ok | ||
if (typeof v !== expectedType) { | ||
@@ -91,0 +92,0 @@ const msg = message || `Expected typeof ${expectedType}, actual typeof: ${typeof v}`; |
@@ -37,3 +37,3 @@ /// <reference lib="es2022" preserve="true" /> | ||
if (typeof globalThis.fetch !== 'function') { | ||
throw new TypeError(`globalThis.fetch is not available`); | ||
throw new TypeError('globalThis.fetch is not available'); | ||
} | ||
@@ -285,3 +285,3 @@ this.cfg = this.normalizeCfg(cfg); | ||
// Error is to be handled upstream | ||
throw new Error(`fetchResponse.body is null`); | ||
throw new Error('fetchResponse.body is null'); | ||
} | ||
@@ -415,3 +415,3 @@ } | ||
const date = new Date(retryAfterStr); | ||
if (!isNaN(date)) { | ||
if (!Number.isNaN(date)) { | ||
timeout = Number(date) - Date.now(); | ||
@@ -422,3 +422,3 @@ } | ||
if (!timeout) { | ||
this.cfg.logger.warn(`retry-after could not be parsed`); | ||
this.cfg.logger.warn('retry-after could not be parsed'); | ||
} | ||
@@ -577,3 +577,3 @@ } | ||
if (req.fullUrl.startsWith('/')) { | ||
console.warn(`Fetcher: url should not start with / when baseUrl is specified`); | ||
console.warn('Fetcher: url should not start with / when baseUrl is specified'); | ||
req.fullUrl = req.fullUrl.slice(1); | ||
@@ -580,0 +580,0 @@ } |
@@ -144,3 +144,3 @@ import { _uniq } from '../array/array.util'; | ||
else { | ||
delete this.schema.optionalField; | ||
this.schema.optionalField = undefined; | ||
} | ||
@@ -279,3 +279,3 @@ return this; | ||
else { | ||
delete schema.optionalField; | ||
schema.optionalField = undefined; | ||
} | ||
@@ -282,0 +282,0 @@ this.schema.properties[k] = schema; |
@@ -0,1 +1,2 @@ | ||
import { _assert } from '../error/assert'; | ||
import { _sortNumbers } from '../number/number.util'; | ||
@@ -11,3 +12,7 @@ /** | ||
export function _average(values) { | ||
return values.reduce((a, b) => a + b) / values.length; | ||
_assert(values.length, '_average is called on empty array'); | ||
let total = 0; | ||
for (const n of values) | ||
total += n; | ||
return total / values.length; | ||
} | ||
@@ -18,3 +23,3 @@ /** | ||
export function _averageOrNull(values) { | ||
return values?.length ? values.reduce((a, b) => a + b) / values.length : null; | ||
return values?.length ? _average(values) : null; | ||
} | ||
@@ -25,4 +30,9 @@ /** | ||
export function _averageWeighted(values, weights) { | ||
const numerator = values.map((value, i) => value * weights[i]).reduce((a, b) => a + b); | ||
const denominator = weights.reduce((a, b) => a + b); | ||
let numerator = 0; | ||
let denominator = 0; | ||
// eslint-disable-next-line unicorn/no-for-loop | ||
for (let i = 0; i < values.length; i++) { | ||
numerator += values[i] * weights[i]; | ||
denominator += weights[i]; | ||
} | ||
return numerator / denominator; | ||
@@ -29,0 +39,0 @@ } |
@@ -20,3 +20,6 @@ /** | ||
return 0; | ||
return this.data.reduce((total, n) => total + n, 0) / this.data.length; | ||
let total = 0; | ||
for (const n of this.data) | ||
total += n; | ||
return total / this.data.length; | ||
} | ||
@@ -23,0 +26,0 @@ /** |
@@ -9,3 +9,3 @@ /* eslint-disable no-bitwise */ | ||
let seed = 0x2f6e2b1; | ||
return function () { | ||
return () => { | ||
// Robert Jenkins’ 32 bit integer hash function | ||
@@ -12,0 +12,0 @@ seed = (seed + 0x7ed55d16 + (seed << 12)) & 0xffffffff; |
@@ -39,6 +39,6 @@ export function _randomInt(minIncl, maxIncl) { | ||
} | ||
else if (incl === '[]') { | ||
if (incl === '[]') { | ||
return x >= min && x <= max; | ||
} | ||
else if (incl === '(]') { | ||
if (incl === '(]') { | ||
return x > min && x <= max; | ||
@@ -45,0 +45,0 @@ } |
import { _isEmpty, _isObject } from '../is.util'; | ||
import { _objectEntries, SKIP } from '../types'; | ||
import { _objectEntries, SKIP, } from '../types'; | ||
/** | ||
@@ -10,14 +10,15 @@ * Returns clone of `obj` with only `props` preserved. | ||
// Start as original object (mutable), DELETE properties that are not whitelisted | ||
return Object.keys(obj).reduce((r, prop) => { | ||
for (const prop of Object.keys(obj)) { | ||
if (!props.includes(prop)) | ||
delete r[prop]; | ||
return r; | ||
}, obj); | ||
delete obj[prop]; | ||
} | ||
return obj; | ||
} | ||
// Start as empty object, pick/add needed properties | ||
return props.reduce((r, prop) => { | ||
const r = {}; | ||
for (const prop of props) { | ||
if (prop in obj) | ||
r[prop] = obj[prop]; | ||
return r; | ||
}, {}); | ||
} | ||
return r; | ||
} | ||
@@ -29,6 +30,14 @@ /** | ||
export function _omit(obj, props, mutate = false) { | ||
return props.reduce((r, prop) => { | ||
delete r[prop]; | ||
return r; | ||
}, mutate ? obj : { ...obj }); | ||
if (mutate) { | ||
for (const prop of props) { | ||
delete obj[prop]; | ||
} | ||
return obj; | ||
} | ||
const r = {}; | ||
for (const prop of Object.keys(obj)) { | ||
if (!props.includes(prop)) | ||
r[prop] = obj[prop]; | ||
} | ||
return r; | ||
} | ||
@@ -44,6 +53,7 @@ /** | ||
export function _mask(obj, props, mutate = false) { | ||
return props.reduce((r, prop) => { | ||
const r = mutate ? obj : _deepCopy(obj); | ||
for (const prop of props) { | ||
_unset(r, prop); | ||
return r; | ||
}, mutate ? obj : _deepCopy(obj)); | ||
} | ||
return r; | ||
} | ||
@@ -77,7 +87,17 @@ /** | ||
export function _filterObject(obj, predicate, mutate = false) { | ||
return Object.keys(obj).reduce((r, k) => { | ||
if (!predicate(k, r[k], obj)) | ||
delete r[k]; | ||
return r; | ||
}, mutate ? obj : { ...obj }); | ||
if (mutate) { | ||
for (const [k, v] of _objectEntries(obj)) { | ||
if (!predicate(k, v, obj)) { | ||
delete obj[k]; | ||
} | ||
} | ||
return obj; | ||
} | ||
const r = {}; | ||
for (const [k, v] of _objectEntries(obj)) { | ||
if (predicate(k, v, obj)) { | ||
r[k] = v; | ||
} | ||
} | ||
return r; | ||
} | ||
@@ -96,6 +116,7 @@ /** | ||
export function _mapValues(obj, mapper, mutate = false) { | ||
return _objectEntries(obj).reduce((map, [k, v]) => { | ||
const map = mutate ? obj : {}; | ||
for (const [k, v] of Object.entries(obj)) { | ||
map[k] = mapper(k, v, obj); | ||
return map; | ||
}, mutate ? obj : {}); | ||
} | ||
return map; | ||
} | ||
@@ -111,6 +132,7 @@ /** | ||
export function _mapKeys(obj, mapper) { | ||
return _objectEntries(obj).reduce((map, [k, v]) => { | ||
const map = {}; | ||
for (const [k, v] of Object.entries(obj)) { | ||
map[mapper(k, v, obj)] = v; | ||
return map; | ||
}, {}); | ||
} | ||
return map; | ||
} | ||
@@ -134,9 +156,10 @@ /** | ||
export function _mapObject(obj, mapper) { | ||
return Object.entries(obj).reduce((map, [k, v]) => { | ||
const map = {}; | ||
for (const [k, v] of Object.entries(obj)) { | ||
const r = mapper(k, v, obj); | ||
if (r !== SKIP) { | ||
map[r[0]] = r[1]; | ||
} | ||
return map; | ||
}, {}); | ||
if (r === SKIP) | ||
continue; | ||
map[r[0]] = r[1]; | ||
} | ||
return map; | ||
} | ||
@@ -229,3 +252,3 @@ export function _findKeyByValue(obj, v) { | ||
} | ||
else if (typeof o === 'object') { | ||
if (typeof o === 'object') { | ||
Object.keys(o).forEach(k => { | ||
@@ -284,6 +307,7 @@ o[k] = _deepTrim(o[k]); | ||
export function _get(obj = {}, path = '') { | ||
return path | ||
return (path | ||
.replaceAll(/\[([^\]]+)]/g, '.$1') | ||
.split('.') | ||
.reduce((o, p) => o?.[p], obj); | ||
// eslint-disable-next-line unicorn/no-array-reduce | ||
.reduce((o, p) => o?.[p], obj)); | ||
} | ||
@@ -311,2 +335,3 @@ /** | ||
} | ||
// eslint-disable-next-line unicorn/no-array-reduce | ||
; | ||
@@ -313,0 +338,0 @@ path.slice(0, -1).reduce((a, c, i) => Object(a[c]) === a[c] // Does the key exist and is its value an object? |
@@ -21,3 +21,3 @@ import { pDefer } from './pDefer'; | ||
*/ | ||
export function pDelayFn(ms = 0, fn) { | ||
export function pDelayFn(ms, fn) { | ||
const p = pDefer(); | ||
@@ -24,0 +24,0 @@ const timer = setTimeout(async () => { |
import { _range } from './array/range'; | ||
import { _assert } from './error/assert'; | ||
import { _isTruthy } from './is.util'; | ||
/** | ||
@@ -78,3 +77,10 @@ * Simple Semver implementation. | ||
maxOrUndefined(items) { | ||
return items.length ? this.max(items) : undefined; | ||
let max; | ||
for (const item of items) { | ||
const input = this.fromInputOrUndefined(item); | ||
if (!max || input?.isAfter(max)) { | ||
max = input; | ||
} | ||
} | ||
return max; | ||
} | ||
@@ -86,7 +92,5 @@ /** | ||
max(items) { | ||
const items2 = items.filter(_isTruthy); | ||
_assert(items2.length, 'semver.max called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item)); | ||
const max = this.maxOrUndefined(items); | ||
_assert(max, 'semver.max called on empty array'); | ||
return max; | ||
} | ||
@@ -97,3 +101,10 @@ /** | ||
minOrUndefined(items) { | ||
return items.length ? this.min(items) : undefined; | ||
let min; | ||
for (const item of items) { | ||
const input = this.fromInputOrUndefined(item); | ||
if (!min || input?.isBefore(min)) { | ||
min = input; | ||
} | ||
} | ||
return min; | ||
} | ||
@@ -105,7 +116,5 @@ /** | ||
min(items) { | ||
const items2 = items.filter(_isTruthy); | ||
_assert(items2.length, 'semver.min called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item)); | ||
const min = this.minOrUndefined(items); | ||
_assert(min, 'semver.min called on empty array'); | ||
return min; | ||
} | ||
@@ -112,0 +121,0 @@ /** |
import { words } from './lodash/words'; | ||
import { _upperFirst } from './string.util'; | ||
export function _camelCase(s) { | ||
// return s.replace(/(_\w)/g, m => m[1]!.toUpperCase()) | ||
return words(s.replaceAll(/['\u2019]/g, '')).reduce((result, word, index) => { | ||
let r = ''; | ||
for (let word of words(s.replaceAll(/['\u2019]/g, ''))) { | ||
word = word.toLowerCase(); | ||
return result + (index ? _upperFirst(word) : word); | ||
}, ''); | ||
r += r ? _upperFirst(word) : word; | ||
} | ||
return r; | ||
} | ||
export function _snakeCase(s) { | ||
return words(s.replaceAll(/['\u2019]/g, '')).reduce((result, word, index) => result + (index ? '_' : '') + word.toLowerCase(), ''); | ||
let r = ''; | ||
for (const word of words(s.replaceAll(/['\u2019]/g, ''))) { | ||
r += (r ? '_' : '') + word.toLowerCase(); | ||
} | ||
return r; | ||
} | ||
export function _kebabCase(s) { | ||
return words(s.replaceAll(/['\u2019]/g, '')).reduce((result, word, index) => result + (index ? '-' : '') + word.toLowerCase(), ''); | ||
let r = ''; | ||
for (const word of words(s.replaceAll(/['\u2019]/g, ''))) { | ||
r += (r ? '-' : '') + word.toLowerCase(); | ||
} | ||
return r; | ||
} |
@@ -6,2 +6,3 @@ // from: https://github.com/lodash/lodash/blob/master/words.js | ||
/** Used to match words composed of alphanumeric characters. */ | ||
// biome-ignore lint/suspicious/noControlCharactersInRegex: ok | ||
const reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; | ||
@@ -8,0 +9,0 @@ function asciiWords(s) { |
@@ -20,3 +20,3 @@ /** | ||
const keys = []; | ||
cycleReplacer ?? (cycleReplacer = function (key, value) { | ||
cycleReplacer ?? (cycleReplacer = (key, value) => { | ||
if (stack[0] === value) | ||
@@ -23,0 +23,0 @@ return '[Circular ~]'; |
@@ -42,3 +42,3 @@ "use strict"; | ||
exports._zip = _zip; | ||
const is_util_1 = require("../is.util"); | ||
const assert_1 = require("../error/assert"); | ||
const types_1 = require("../types"); | ||
@@ -58,5 +58,7 @@ /** | ||
function _chunk(array, size = 1) { | ||
return array.reduce((arr, item, idx) => { | ||
return idx % size === 0 ? [...arr, [item]] : [...arr.slice(0, -1), [...arr.slice(-1)[0], item]]; | ||
}, []); | ||
const a = []; | ||
for (let i = 0; i < array.length; i += size) { | ||
a.push(array.slice(i, i + size)); | ||
} | ||
return a; | ||
} | ||
@@ -122,12 +124,9 @@ /** | ||
function _uniqBy(arr, mapper) { | ||
return [ | ||
...arr | ||
.reduce((map, item, index) => { | ||
const key = item === null || item === undefined ? item : mapper(item, index); | ||
if (!map.has(key)) | ||
map.set(key, item); | ||
return map; | ||
}, new Map()) | ||
.values(), | ||
]; | ||
const map = new Map(); | ||
for (const [i, item] of arr.entries()) { | ||
const key = item === undefined || item === null ? item : mapper(item, i); | ||
if (!map.has(key)) | ||
map.set(key, item); | ||
} | ||
return [...map.values()]; | ||
} | ||
@@ -175,9 +174,10 @@ /** | ||
function _groupBy(items, mapper) { | ||
return items.reduce((map, item, index) => { | ||
const res = mapper(item, index); | ||
if (res !== undefined) { | ||
map[res] = [...(map[res] || []), item]; | ||
} | ||
return map; | ||
}, {}); | ||
const map = {}; | ||
for (const [i, item] of items.entries()) { | ||
const key = mapper(item, i); | ||
if (key === undefined) | ||
continue; | ||
(map[key] ||= []).push(item); | ||
} | ||
return map; | ||
} | ||
@@ -330,3 +330,7 @@ /** | ||
function _difference(source, ...diffs) { | ||
return diffs.reduce((a, b) => a.filter(c => !b.includes(c)), source); | ||
let a = source; | ||
for (const b of diffs) { | ||
a = a.filter(c => !b.includes(c)); | ||
} | ||
return a; | ||
} | ||
@@ -416,6 +420,11 @@ /** | ||
function _minOrUndefined(array) { | ||
const a = array.filter(is_util_1._isNotNullish); | ||
if (!a.length) | ||
return; | ||
return a.reduce((min, item) => (min <= item ? min : item)); | ||
let min; | ||
for (const item of array) { | ||
if (item === undefined || item === null) | ||
continue; | ||
if (min === undefined || item < min) { | ||
min = item; | ||
} | ||
} | ||
return min; | ||
} | ||
@@ -426,12 +435,16 @@ /** | ||
function _min(array) { | ||
const a = array.filter(is_util_1._isNotNullish); | ||
if (!a.length) | ||
throw new Error('_min called on empty array'); | ||
return a.reduce((min, item) => (min <= item ? min : item)); | ||
const min = _minOrUndefined(array); | ||
(0, assert_1._assert)(min !== undefined, '_min called on empty array'); | ||
return min; | ||
} | ||
function _maxOrUndefined(array) { | ||
const a = array.filter(is_util_1._isNotNullish); | ||
if (!a.length) | ||
return; | ||
return a.reduce((max, item) => (max >= item ? max : item)); | ||
let max; | ||
for (const item of array) { | ||
if (item === undefined || item === null) | ||
continue; | ||
if (max === undefined || item > max) { | ||
max = item; | ||
} | ||
} | ||
return max; | ||
} | ||
@@ -442,11 +455,9 @@ /** | ||
function _max(array) { | ||
const a = array.filter(is_util_1._isNotNullish); | ||
if (!a.length) | ||
throw new Error('_max called on empty array'); | ||
return a.reduce((max, item) => (max >= item ? max : item)); | ||
const max = _maxOrUndefined(array); | ||
(0, assert_1._assert)(max !== undefined, '_max called on empty array'); | ||
return max; | ||
} | ||
function _maxBy(array, mapper) { | ||
const max = _maxByOrUndefined(array, mapper); | ||
if (max === undefined) | ||
throw new Error(`_maxBy returned undefined`); | ||
(0, assert_1._assert)(max !== undefined, '_maxBy returned undefined'); | ||
return max; | ||
@@ -456,4 +467,3 @@ } | ||
const min = _minByOrUndefined(array, mapper); | ||
if (min === undefined) | ||
throw new Error(`_minBy returned undefined`); | ||
(0, assert_1._assert)(min !== undefined, '_minBy returned undefined'); | ||
return min; | ||
@@ -460,0 +470,0 @@ } |
@@ -5,3 +5,2 @@ "use strict"; | ||
const assert_1 = require("../error/assert"); | ||
const is_util_1 = require("../is.util"); | ||
const iterable2_1 = require("../iter/iterable2"); | ||
@@ -500,3 +499,3 @@ const localTime_1 = require("./localTime"); | ||
if (input instanceof Date) | ||
return !isNaN(input.getDate()); | ||
return !Number.isNaN(input.getDate()); | ||
return this.isValidString(input); | ||
@@ -521,3 +520,3 @@ } | ||
if (input instanceof Date) { | ||
if (isNaN(input.getDate())) | ||
if (Number.isNaN(input.getDate())) | ||
return; | ||
@@ -580,3 +579,3 @@ return new LocalDate(input.getFullYear(), input.getMonth() + 1, input.getDate()); | ||
fromDate(d) { | ||
(0, assert_1._assert)(!isNaN(d.getDate()), `localDate.fromDate is called on Date object that is invalid`); | ||
(0, assert_1._assert)(!Number.isNaN(d.getDate()), 'localDate.fromDate is called on Date object that is invalid'); | ||
return new LocalDate(d.getFullYear(), d.getMonth() + 1, d.getDate()); | ||
@@ -589,3 +588,3 @@ } | ||
fromDateInUTC(d) { | ||
(0, assert_1._assert)(!isNaN(d.getDate()), `localDate.fromDateInUTC is called on Date object that is invalid`); | ||
(0, assert_1._assert)(!Number.isNaN(d.getDate()), 'localDate.fromDateInUTC is called on Date object that is invalid'); | ||
return new LocalDate(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate()); | ||
@@ -608,3 +607,12 @@ } | ||
minOrUndefined(items) { | ||
return items.length ? this.min(items) : undefined; | ||
let min; | ||
for (const item of items) { | ||
if (!item) | ||
continue; | ||
const ld = this.fromInput(item); | ||
if (!min || ld.isBefore(min)) { | ||
min = ld; | ||
} | ||
} | ||
return min; | ||
} | ||
@@ -616,7 +624,5 @@ /** | ||
min(items) { | ||
const items2 = items.filter(is_util_1._isTruthy); | ||
(0, assert_1._assert)(items2.length, 'localDate.min called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item)); | ||
const min = this.minOrUndefined(items); | ||
(0, assert_1._assert)(min, 'localDate.min called on empty array'); | ||
return min; | ||
} | ||
@@ -627,3 +633,12 @@ /** | ||
maxOrUndefined(items) { | ||
return items.length ? this.max(items) : undefined; | ||
let max; | ||
for (const item of items) { | ||
if (!item) | ||
continue; | ||
const ld = this.fromInput(item); | ||
if (!max || ld.isAfter(max)) { | ||
max = ld; | ||
} | ||
} | ||
return max; | ||
} | ||
@@ -635,7 +650,5 @@ /** | ||
max(items) { | ||
const items2 = items.filter(is_util_1._isTruthy); | ||
(0, assert_1._assert)(items2.length, 'localDate.max called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item)); | ||
const max = this.maxOrUndefined(items); | ||
(0, assert_1._assert)(max, 'localDate.max called on empty array'); | ||
return max; | ||
} | ||
@@ -642,0 +655,0 @@ /** |
@@ -5,3 +5,2 @@ "use strict"; | ||
const assert_1 = require("../error/assert"); | ||
const is_util_1 = require("../is.util"); | ||
const time_util_1 = require("../time/time.util"); | ||
@@ -681,3 +680,3 @@ const localDate_1 = require("./localDate"); | ||
if (input instanceof Date) | ||
return !isNaN(input.getDate()); | ||
return !Number.isNaN(input.getDate()); | ||
// We currently don't validate Unixtimestamp input, treat it as always valid | ||
@@ -703,3 +702,3 @@ if (typeof input === 'number') | ||
if (input instanceof Date) { | ||
if (isNaN(input.getDate())) | ||
if (Number.isNaN(input.getDate())) | ||
return; | ||
@@ -768,3 +767,3 @@ return new LocalTime(input); | ||
const d = new Date(s); | ||
return isNaN(d.getDate()) ? undefined : d; | ||
return Number.isNaN(d.getDate()) ? undefined : d; | ||
} | ||
@@ -797,3 +796,3 @@ const o = { | ||
fromDate(date) { | ||
(0, assert_1._assert)(!isNaN(date.getDate()), `localTime.fromDate is called on Date object that is invalid`); | ||
(0, assert_1._assert)(!Number.isNaN(date.getDate()), 'localTime.fromDate is called on Date object that is invalid'); | ||
return new LocalTime(date); | ||
@@ -853,20 +852,34 @@ } | ||
minOrUndefined(items) { | ||
return items.length ? this.min(items) : undefined; | ||
let min; | ||
for (const item of items) { | ||
if (!item) | ||
continue; | ||
const lt = this.fromInput(item); | ||
if (!min || lt.$date.valueOf() < min.$date.valueOf()) { | ||
min = lt; | ||
} | ||
} | ||
return min; | ||
} | ||
min(items) { | ||
const items2 = items.filter(is_util_1._isTruthy); | ||
(0, assert_1._assert)(items2.length, 'localTime.min called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item)); | ||
const min = this.minOrUndefined(items); | ||
(0, assert_1._assert)(min, 'localTime.min called on empty array'); | ||
return min; | ||
} | ||
maxOrUndefined(items) { | ||
return items.length ? this.max(items) : undefined; | ||
let max; | ||
for (const item of items) { | ||
if (!item) | ||
continue; | ||
const lt = this.fromInput(item); | ||
if (!max || lt.$date.valueOf() > max.$date.valueOf()) { | ||
max = lt; | ||
} | ||
} | ||
return max; | ||
} | ||
max(items) { | ||
const items2 = items.filter(is_util_1._isTruthy); | ||
(0, assert_1._assert)(items2.length, 'localTime.max called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item)); | ||
const max = this.maxOrUndefined(items); | ||
(0, assert_1._assert)(max, 'localTime.max called on empty array'); | ||
return max; | ||
} | ||
@@ -907,3 +920,3 @@ } | ||
} | ||
else if (date.getTime() >= startOfThisYear.getTime()) { | ||
if (date.getTime() >= startOfThisYear.getTime()) { | ||
return year; | ||
@@ -910,0 +923,0 @@ } |
@@ -63,3 +63,3 @@ "use strict"; | ||
const msg = message || | ||
[`not deeply equal`, `expected: ${(0, __1._stringify)(expected)}`, `got : ${(0, __1._stringify)(actual)}`] | ||
['not deeply equal', `expected: ${(0, __1._stringify)(expected)}`, `got : ${(0, __1._stringify)(actual)}`] | ||
.filter(Boolean) | ||
@@ -100,2 +100,3 @@ .join('\n'); | ||
function _assertTypeOf(v, expectedType, message) { | ||
// biome-ignore lint/suspicious/useValidTypeof: ok | ||
if (typeof v !== expectedType) { | ||
@@ -102,0 +103,0 @@ const msg = message || `Expected typeof ${expectedType}, actual typeof: ${typeof v}`; |
@@ -48,3 +48,3 @@ "use strict"; | ||
if (typeof globalThis.fetch !== 'function') { | ||
throw new TypeError(`globalThis.fetch is not available`); | ||
throw new TypeError('globalThis.fetch is not available'); | ||
} | ||
@@ -293,3 +293,3 @@ this.cfg = this.normalizeCfg(cfg); | ||
// Error is to be handled upstream | ||
throw new Error(`fetchResponse.body is null`); | ||
throw new Error('fetchResponse.body is null'); | ||
} | ||
@@ -423,3 +423,3 @@ } | ||
const date = new Date(retryAfterStr); | ||
if (!isNaN(date)) { | ||
if (!Number.isNaN(date)) { | ||
timeout = Number(date) - Date.now(); | ||
@@ -430,3 +430,3 @@ } | ||
if (!timeout) { | ||
this.cfg.logger.warn(`retry-after could not be parsed`); | ||
this.cfg.logger.warn('retry-after could not be parsed'); | ||
} | ||
@@ -584,3 +584,3 @@ } | ||
if (req.fullUrl.startsWith('/')) { | ||
console.warn(`Fetcher: url should not start with / when baseUrl is specified`); | ||
console.warn('Fetcher: url should not start with / when baseUrl is specified'); | ||
req.fullUrl = req.fullUrl.slice(1); | ||
@@ -587,0 +587,0 @@ } |
@@ -147,3 +147,3 @@ "use strict"; | ||
else { | ||
delete this.schema.optionalField; | ||
this.schema.optionalField = undefined; | ||
} | ||
@@ -285,3 +285,3 @@ return this; | ||
else { | ||
delete schema.optionalField; | ||
schema.optionalField = undefined; | ||
} | ||
@@ -288,0 +288,0 @@ this.schema.properties[k] = schema; |
@@ -9,2 +9,3 @@ "use strict"; | ||
exports._median = _median; | ||
const assert_1 = require("../error/assert"); | ||
const number_util_1 = require("../number/number.util"); | ||
@@ -20,3 +21,7 @@ /** | ||
function _average(values) { | ||
return values.reduce((a, b) => a + b) / values.length; | ||
(0, assert_1._assert)(values.length, '_average is called on empty array'); | ||
let total = 0; | ||
for (const n of values) | ||
total += n; | ||
return total / values.length; | ||
} | ||
@@ -27,3 +32,3 @@ /** | ||
function _averageOrNull(values) { | ||
return values?.length ? values.reduce((a, b) => a + b) / values.length : null; | ||
return values?.length ? _average(values) : null; | ||
} | ||
@@ -34,4 +39,9 @@ /** | ||
function _averageWeighted(values, weights) { | ||
const numerator = values.map((value, i) => value * weights[i]).reduce((a, b) => a + b); | ||
const denominator = weights.reduce((a, b) => a + b); | ||
let numerator = 0; | ||
let denominator = 0; | ||
// eslint-disable-next-line unicorn/no-for-loop | ||
for (let i = 0; i < values.length; i++) { | ||
numerator += values[i] * weights[i]; | ||
denominator += weights[i]; | ||
} | ||
return numerator / denominator; | ||
@@ -38,0 +48,0 @@ } |
@@ -23,3 +23,6 @@ "use strict"; | ||
return 0; | ||
return this.data.reduce((total, n) => total + n, 0) / this.data.length; | ||
let total = 0; | ||
for (const n of this.data) | ||
total += n; | ||
return total / this.data.length; | ||
} | ||
@@ -26,0 +29,0 @@ /** |
@@ -12,3 +12,3 @@ "use strict"; | ||
let seed = 0x2f6e2b1; | ||
return function () { | ||
return () => { | ||
// Robert Jenkins’ 32 bit integer hash function | ||
@@ -15,0 +15,0 @@ seed = (seed + 0x7ed55d16 + (seed << 12)) & 0xffffffff; |
@@ -50,6 +50,6 @@ "use strict"; | ||
} | ||
else if (incl === '[]') { | ||
if (incl === '[]') { | ||
return x >= min && x <= max; | ||
} | ||
else if (incl === '(]') { | ||
if (incl === '(]') { | ||
return x > min && x <= max; | ||
@@ -56,0 +56,0 @@ } |
@@ -1,3 +0,2 @@ | ||
import type { AnyObject, ObjectMapper, ObjectPredicate, ValueOf } from '../types'; | ||
import { KeyValueTuple, Reviver, SKIP } from '../types'; | ||
import { AnyObject, KeyValueTuple, ObjectMapper, ObjectPredicate, Reviver, SKIP, ValueOf } from '../types'; | ||
/** | ||
@@ -4,0 +3,0 @@ * Returns clone of `obj` with only `props` preserved. |
@@ -38,14 +38,15 @@ "use strict"; | ||
// Start as original object (mutable), DELETE properties that are not whitelisted | ||
return Object.keys(obj).reduce((r, prop) => { | ||
for (const prop of Object.keys(obj)) { | ||
if (!props.includes(prop)) | ||
delete r[prop]; | ||
return r; | ||
}, obj); | ||
delete obj[prop]; | ||
} | ||
return obj; | ||
} | ||
// Start as empty object, pick/add needed properties | ||
return props.reduce((r, prop) => { | ||
const r = {}; | ||
for (const prop of props) { | ||
if (prop in obj) | ||
r[prop] = obj[prop]; | ||
return r; | ||
}, {}); | ||
} | ||
return r; | ||
} | ||
@@ -57,6 +58,14 @@ /** | ||
function _omit(obj, props, mutate = false) { | ||
return props.reduce((r, prop) => { | ||
delete r[prop]; | ||
return r; | ||
}, mutate ? obj : { ...obj }); | ||
if (mutate) { | ||
for (const prop of props) { | ||
delete obj[prop]; | ||
} | ||
return obj; | ||
} | ||
const r = {}; | ||
for (const prop of Object.keys(obj)) { | ||
if (!props.includes(prop)) | ||
r[prop] = obj[prop]; | ||
} | ||
return r; | ||
} | ||
@@ -72,6 +81,7 @@ /** | ||
function _mask(obj, props, mutate = false) { | ||
return props.reduce((r, prop) => { | ||
const r = mutate ? obj : _deepCopy(obj); | ||
for (const prop of props) { | ||
_unset(r, prop); | ||
return r; | ||
}, mutate ? obj : _deepCopy(obj)); | ||
} | ||
return r; | ||
} | ||
@@ -105,7 +115,17 @@ /** | ||
function _filterObject(obj, predicate, mutate = false) { | ||
return Object.keys(obj).reduce((r, k) => { | ||
if (!predicate(k, r[k], obj)) | ||
delete r[k]; | ||
return r; | ||
}, mutate ? obj : { ...obj }); | ||
if (mutate) { | ||
for (const [k, v] of (0, types_1._objectEntries)(obj)) { | ||
if (!predicate(k, v, obj)) { | ||
delete obj[k]; | ||
} | ||
} | ||
return obj; | ||
} | ||
const r = {}; | ||
for (const [k, v] of (0, types_1._objectEntries)(obj)) { | ||
if (predicate(k, v, obj)) { | ||
r[k] = v; | ||
} | ||
} | ||
return r; | ||
} | ||
@@ -124,6 +144,7 @@ /** | ||
function _mapValues(obj, mapper, mutate = false) { | ||
return (0, types_1._objectEntries)(obj).reduce((map, [k, v]) => { | ||
const map = mutate ? obj : {}; | ||
for (const [k, v] of Object.entries(obj)) { | ||
map[k] = mapper(k, v, obj); | ||
return map; | ||
}, mutate ? obj : {}); | ||
} | ||
return map; | ||
} | ||
@@ -139,6 +160,7 @@ /** | ||
function _mapKeys(obj, mapper) { | ||
return (0, types_1._objectEntries)(obj).reduce((map, [k, v]) => { | ||
const map = {}; | ||
for (const [k, v] of Object.entries(obj)) { | ||
map[mapper(k, v, obj)] = v; | ||
return map; | ||
}, {}); | ||
} | ||
return map; | ||
} | ||
@@ -162,9 +184,10 @@ /** | ||
function _mapObject(obj, mapper) { | ||
return Object.entries(obj).reduce((map, [k, v]) => { | ||
const map = {}; | ||
for (const [k, v] of Object.entries(obj)) { | ||
const r = mapper(k, v, obj); | ||
if (r !== types_1.SKIP) { | ||
map[r[0]] = r[1]; | ||
} | ||
return map; | ||
}, {}); | ||
if (r === types_1.SKIP) | ||
continue; | ||
map[r[0]] = r[1]; | ||
} | ||
return map; | ||
} | ||
@@ -256,3 +279,3 @@ function _findKeyByValue(obj, v) { | ||
} | ||
else if (typeof o === 'object') { | ||
if (typeof o === 'object') { | ||
Object.keys(o).forEach(k => { | ||
@@ -311,6 +334,7 @@ o[k] = _deepTrim(o[k]); | ||
function _get(obj = {}, path = '') { | ||
return path | ||
return (path | ||
.replaceAll(/\[([^\]]+)]/g, '.$1') | ||
.split('.') | ||
.reduce((o, p) => o?.[p], obj); | ||
// eslint-disable-next-line unicorn/no-array-reduce | ||
.reduce((o, p) => o?.[p], obj)); | ||
} | ||
@@ -338,2 +362,3 @@ /** | ||
} | ||
// eslint-disable-next-line unicorn/no-array-reduce | ||
; | ||
@@ -340,0 +365,0 @@ path.slice(0, -1).reduce((a, c, i) => Object(a[c]) === a[c] // Does the key exist and is its value an object? |
@@ -1,2 +0,2 @@ | ||
import type { PromisableFunction } from '../types'; | ||
import type { NumberOfMilliseconds, PromisableFunction } from '../types'; | ||
import { DeferredPromise } from './pDefer'; | ||
@@ -9,3 +9,3 @@ /** | ||
*/ | ||
export declare function pDelay<T>(ms?: number, value?: T): Promise<T>; | ||
export declare function pDelay<T>(ms?: NumberOfMilliseconds, value?: T): Promise<T>; | ||
/** | ||
@@ -20,2 +20,2 @@ * Promisified version of setTimeout. | ||
*/ | ||
export declare function pDelayFn<T>(ms: number | undefined, fn: PromisableFunction<T>): DeferredPromise<T>; | ||
export declare function pDelayFn<T>(ms: NumberOfMilliseconds, fn: PromisableFunction<T>): DeferredPromise<T>; |
@@ -25,3 +25,3 @@ "use strict"; | ||
*/ | ||
function pDelayFn(ms = 0, fn) { | ||
function pDelayFn(ms, fn) { | ||
const p = (0, pDefer_1.pDefer)(); | ||
@@ -28,0 +28,0 @@ const timer = setTimeout(async () => { |
@@ -7,3 +7,2 @@ "use strict"; | ||
const assert_1 = require("./error/assert"); | ||
const is_util_1 = require("./is.util"); | ||
/** | ||
@@ -84,3 +83,10 @@ * Simple Semver implementation. | ||
maxOrUndefined(items) { | ||
return items.length ? this.max(items) : undefined; | ||
let max; | ||
for (const item of items) { | ||
const input = this.fromInputOrUndefined(item); | ||
if (!max || input?.isAfter(max)) { | ||
max = input; | ||
} | ||
} | ||
return max; | ||
} | ||
@@ -92,7 +98,5 @@ /** | ||
max(items) { | ||
const items2 = items.filter(is_util_1._isTruthy); | ||
(0, assert_1._assert)(items2.length, 'semver.max called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item)); | ||
const max = this.maxOrUndefined(items); | ||
(0, assert_1._assert)(max, 'semver.max called on empty array'); | ||
return max; | ||
} | ||
@@ -103,3 +107,10 @@ /** | ||
minOrUndefined(items) { | ||
return items.length ? this.min(items) : undefined; | ||
let min; | ||
for (const item of items) { | ||
const input = this.fromInputOrUndefined(item); | ||
if (!min || input?.isBefore(min)) { | ||
min = input; | ||
} | ||
} | ||
return min; | ||
} | ||
@@ -111,7 +122,5 @@ /** | ||
min(items) { | ||
const items2 = items.filter(is_util_1._isTruthy); | ||
(0, assert_1._assert)(items2.length, 'semver.min called on empty array'); | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item)); | ||
const min = this.minOrUndefined(items); | ||
(0, assert_1._assert)(min, 'semver.min called on empty array'); | ||
return min; | ||
} | ||
@@ -118,0 +127,0 @@ /** |
@@ -9,13 +9,22 @@ "use strict"; | ||
function _camelCase(s) { | ||
// return s.replace(/(_\w)/g, m => m[1]!.toUpperCase()) | ||
return (0, words_1.words)(s.replaceAll(/['\u2019]/g, '')).reduce((result, word, index) => { | ||
let r = ''; | ||
for (let word of (0, words_1.words)(s.replaceAll(/['\u2019]/g, ''))) { | ||
word = word.toLowerCase(); | ||
return result + (index ? (0, string_util_1._upperFirst)(word) : word); | ||
}, ''); | ||
r += r ? (0, string_util_1._upperFirst)(word) : word; | ||
} | ||
return r; | ||
} | ||
function _snakeCase(s) { | ||
return (0, words_1.words)(s.replaceAll(/['\u2019]/g, '')).reduce((result, word, index) => result + (index ? '_' : '') + word.toLowerCase(), ''); | ||
let r = ''; | ||
for (const word of (0, words_1.words)(s.replaceAll(/['\u2019]/g, ''))) { | ||
r += (r ? '_' : '') + word.toLowerCase(); | ||
} | ||
return r; | ||
} | ||
function _kebabCase(s) { | ||
return (0, words_1.words)(s.replaceAll(/['\u2019]/g, '')).reduce((result, word, index) => result + (index ? '-' : '') + word.toLowerCase(), ''); | ||
let r = ''; | ||
for (const word of (0, words_1.words)(s.replaceAll(/['\u2019]/g, ''))) { | ||
r += (r ? '-' : '') + word.toLowerCase(); | ||
} | ||
return r; | ||
} |
@@ -9,2 +9,3 @@ "use strict"; | ||
/** Used to match words composed of alphanumeric characters. */ | ||
// biome-ignore lint/suspicious/noControlCharactersInRegex: ok | ||
const reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; | ||
@@ -11,0 +12,0 @@ function asciiWords(s) { |
@@ -23,3 +23,3 @@ "use strict"; | ||
const keys = []; | ||
cycleReplacer ??= function (key, value) { | ||
cycleReplacer ??= (key, value) => { | ||
if (stack[0] === value) | ||
@@ -26,0 +26,0 @@ return '[Circular ~]'; |
{ | ||
"name": "@naturalcycles/js-lib", | ||
"version": "14.249.0", | ||
"version": "14.250.0", | ||
"scripts": { | ||
@@ -5,0 +5,0 @@ "prepare": "husky", |
@@ -1,2 +0,2 @@ | ||
import { _isNotNullish } from '../is.util' | ||
import { _assert } from '../error/assert' | ||
import { | ||
@@ -25,5 +25,7 @@ AbortablePredicate, | ||
export function _chunk<T>(array: readonly T[], size = 1): T[][] { | ||
return array.reduce((arr, item, idx) => { | ||
return idx % size === 0 ? [...arr, [item]] : [...arr.slice(0, -1), [...arr.slice(-1)[0]!, item]] | ||
}, [] as T[][]) | ||
const a: T[][] = [] | ||
for (let i = 0; i < array.length; i += size) { | ||
a.push(array.slice(i, i + size)) | ||
} | ||
return a | ||
} | ||
@@ -92,13 +94,8 @@ | ||
export function _uniqBy<T>(arr: readonly T[], mapper: Mapper<T, any>): T[] { | ||
return [ | ||
...arr | ||
.reduce((map, item, index) => { | ||
const key = item === null || item === undefined ? item : mapper(item, index) | ||
if (!map.has(key)) map.set(key, item) | ||
return map | ||
}, new Map()) | ||
.values(), | ||
] | ||
const map = new Map<any, T>() | ||
for (const [i, item] of arr.entries()) { | ||
const key = item === undefined || item === null ? item : mapper(item, i) | ||
if (!map.has(key)) map.set(key, item) | ||
} | ||
return [...map.values()] | ||
} | ||
@@ -159,12 +156,9 @@ | ||
export function _groupBy<T>(items: readonly T[], mapper: Mapper<T, any>): StringMap<T[]> { | ||
return items.reduce( | ||
(map, item, index) => { | ||
const res = mapper(item, index) | ||
if (res !== undefined) { | ||
map[res] = [...(map[res] || []), item] | ||
} | ||
return map | ||
}, | ||
{} as StringMap<T[]>, | ||
) | ||
const map: StringMap<T[]> = {} | ||
for (const [i, item] of items.entries()) { | ||
const key = mapper(item, i) | ||
if (key === undefined) continue | ||
;(map[key] ||= []).push(item) | ||
} | ||
return map | ||
} | ||
@@ -348,3 +342,7 @@ | ||
export function _difference<T>(source: T[], ...diffs: T[][]): T[] { | ||
return diffs.reduce((a, b) => a.filter(c => !b.includes(c)), source) | ||
let a = source | ||
for (const b of diffs) { | ||
a = a.filter(c => !b.includes(c)) | ||
} | ||
return a | ||
} | ||
@@ -449,5 +447,10 @@ | ||
export function _minOrUndefined<T>(array: readonly T[]): NonNullable<T> | undefined { | ||
const a = array.filter(_isNotNullish) | ||
if (!a.length) return | ||
return a.reduce((min, item) => (min <= item ? min : item)) | ||
let min: NonNullable<T> | undefined | ||
for (const item of array) { | ||
if (item === undefined || item === null) continue | ||
if (min === undefined || item < min) { | ||
min = item as NonNullable<T> | ||
} | ||
} | ||
return min | ||
} | ||
@@ -459,11 +462,16 @@ | ||
export function _min<T>(array: readonly T[]): NonNullable<T> { | ||
const a = array.filter(_isNotNullish) | ||
if (!a.length) throw new Error('_min called on empty array') | ||
return a.reduce((min, item) => (min <= item ? min : item)) | ||
const min = _minOrUndefined(array) | ||
_assert(min !== undefined, '_min called on empty array') | ||
return min | ||
} | ||
export function _maxOrUndefined<T>(array: readonly T[]): NonNullable<T> | undefined { | ||
const a = array.filter(_isNotNullish) | ||
if (!a.length) return | ||
return a.reduce((max, item) => (max >= item ? max : item)) | ||
let max: NonNullable<T> | undefined | ||
for (const item of array) { | ||
if (item === undefined || item === null) continue | ||
if (max === undefined || item > max) { | ||
max = item as NonNullable<T> | ||
} | ||
} | ||
return max | ||
} | ||
@@ -475,5 +483,5 @@ | ||
export function _max<T>(array: readonly T[]): NonNullable<T> { | ||
const a = array.filter(_isNotNullish) | ||
if (!a.length) throw new Error('_max called on empty array') | ||
return a.reduce((max, item) => (max >= item ? max : item)) | ||
const max = _maxOrUndefined(array) | ||
_assert(max !== undefined, '_max called on empty array') | ||
return max | ||
} | ||
@@ -483,3 +491,3 @@ | ||
const max = _maxByOrUndefined(array, mapper) | ||
if (max === undefined) throw new Error(`_maxBy returned undefined`) | ||
_assert(max !== undefined, '_maxBy returned undefined') | ||
return max | ||
@@ -490,3 +498,3 @@ } | ||
const min = _minByOrUndefined(array, mapper) | ||
if (min === undefined) throw new Error(`_minBy returned undefined`) | ||
_assert(min !== undefined, '_minBy returned undefined') | ||
return min | ||
@@ -493,0 +501,0 @@ } |
import { _assert } from '../error/assert' | ||
import { _isTruthy } from '../is.util' | ||
import { Iterable2 } from '../iter/iterable2' | ||
@@ -564,3 +563,3 @@ import type { | ||
if (input instanceof LocalDate) return true | ||
if (input instanceof Date) return !isNaN(input.getDate()) | ||
if (input instanceof Date) return !Number.isNaN(input.getDate()) | ||
return this.isValidString(input) | ||
@@ -585,3 +584,3 @@ } | ||
if (input instanceof Date) { | ||
if (isNaN(input.getDate())) return | ||
if (Number.isNaN(input.getDate())) return | ||
return new LocalDate(input.getFullYear(), input.getMonth() + 1, input.getDate()) | ||
@@ -655,3 +654,6 @@ } | ||
fromDate(d: Date): LocalDate { | ||
_assert(!isNaN(d.getDate()), `localDate.fromDate is called on Date object that is invalid`) | ||
_assert( | ||
!Number.isNaN(d.getDate()), | ||
'localDate.fromDate is called on Date object that is invalid', | ||
) | ||
return new LocalDate(d.getFullYear(), d.getMonth() + 1, d.getDate()) | ||
@@ -665,3 +667,6 @@ } | ||
fromDateInUTC(d: Date): LocalDate { | ||
_assert(!isNaN(d.getDate()), `localDate.fromDateInUTC is called on Date object that is invalid`) | ||
_assert( | ||
!Number.isNaN(d.getDate()), | ||
'localDate.fromDateInUTC is called on Date object that is invalid', | ||
) | ||
return new LocalDate(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate()) | ||
@@ -687,3 +692,11 @@ } | ||
minOrUndefined(items: LocalDateInputNullable[]): LocalDate | undefined { | ||
return items.length ? this.min(items) : undefined | ||
let min: LocalDate | undefined | ||
for (const item of items) { | ||
if (!item) continue | ||
const ld = this.fromInput(item) | ||
if (!min || ld.isBefore(min)) { | ||
min = ld | ||
} | ||
} | ||
return min | ||
} | ||
@@ -696,8 +709,5 @@ | ||
min(items: LocalDateInputNullable[]): LocalDate { | ||
const items2 = items.filter(_isTruthy) | ||
_assert(items2.length, 'localDate.min called on empty array') | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item)) | ||
const min = this.minOrUndefined(items) | ||
_assert(min, 'localDate.min called on empty array') | ||
return min | ||
} | ||
@@ -709,3 +719,11 @@ | ||
maxOrUndefined(items: LocalDateInputNullable[]): LocalDate | undefined { | ||
return items.length ? this.max(items) : undefined | ||
let max: LocalDate | undefined | ||
for (const item of items) { | ||
if (!item) continue | ||
const ld = this.fromInput(item) | ||
if (!max || ld.isAfter(max)) { | ||
max = ld | ||
} | ||
} | ||
return max | ||
} | ||
@@ -718,8 +736,5 @@ | ||
max(items: LocalDateInputNullable[]): LocalDate { | ||
const items2 = items.filter(_isTruthy) | ||
_assert(items2.length, 'localDate.max called on empty array') | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item)) | ||
const max = this.maxOrUndefined(items) | ||
_assert(max, 'localDate.max called on empty array') | ||
return max | ||
} | ||
@@ -726,0 +741,0 @@ |
import { _assert } from '../error/assert' | ||
import { _isTruthy } from '../is.util' | ||
import { _ms } from '../time/time.util' | ||
@@ -364,3 +363,3 @@ import type { | ||
let r | ||
let r: number | ||
@@ -768,3 +767,3 @@ if (unit === 'year') { | ||
if (input instanceof LocalTime) return true | ||
if (input instanceof Date) return !isNaN(input.getDate()) | ||
if (input instanceof Date) return !Number.isNaN(input.getDate()) | ||
// We currently don't validate Unixtimestamp input, treat it as always valid | ||
@@ -790,3 +789,3 @@ if (typeof input === 'number') return true | ||
if (input instanceof Date) { | ||
if (isNaN(input.getDate())) return | ||
if (Number.isNaN(input.getDate())) return | ||
return new LocalTime(input) | ||
@@ -852,3 +851,3 @@ } | ||
const d = new Date(s) | ||
return isNaN(d.getDate()) ? undefined : d | ||
return Number.isNaN(d.getDate()) ? undefined : d | ||
} | ||
@@ -887,3 +886,6 @@ const o: DateTimeObject = { | ||
fromDate(date: Date): LocalTime { | ||
_assert(!isNaN(date.getDate()), `localTime.fromDate is called on Date object that is invalid`) | ||
_assert( | ||
!Number.isNaN(date.getDate()), | ||
'localTime.fromDate is called on Date object that is invalid', | ||
) | ||
return new LocalTime(date) | ||
@@ -951,25 +953,35 @@ } | ||
minOrUndefined(items: LocalTimeInputNullable[]): LocalTime | undefined { | ||
return items.length ? this.min(items) : undefined | ||
let min: LocalTime | undefined | ||
for (const item of items) { | ||
if (!item) continue | ||
const lt = this.fromInput(item) | ||
if (!min || lt.$date.valueOf() < min.$date.valueOf()) { | ||
min = lt | ||
} | ||
} | ||
return min | ||
} | ||
min(items: LocalTimeInputNullable[]): LocalTime { | ||
const items2 = items.filter(_isTruthy) | ||
_assert(items2.length, 'localTime.min called on empty array') | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((min, item) => (min.$date.valueOf() <= item.$date.valueOf() ? min : item)) | ||
const min = this.minOrUndefined(items) | ||
_assert(min, 'localTime.min called on empty array') | ||
return min | ||
} | ||
maxOrUndefined(items: LocalTimeInputNullable[]): LocalTime | undefined { | ||
return items.length ? this.max(items) : undefined | ||
let max: LocalTime | undefined | ||
for (const item of items) { | ||
if (!item) continue | ||
const lt = this.fromInput(item) | ||
if (!max || lt.$date.valueOf() > max.$date.valueOf()) { | ||
max = lt | ||
} | ||
} | ||
return max | ||
} | ||
max(items: LocalTimeInputNullable[]): LocalTime { | ||
const items2 = items.filter(_isTruthy) | ||
_assert(items2.length, 'localTime.max called on empty array') | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((max, item) => (max.$date.valueOf() >= item.$date.valueOf() ? max : item)) | ||
const max = this.maxOrUndefined(items) | ||
_assert(max, 'localTime.max called on empty array') | ||
return max | ||
} | ||
@@ -1016,3 +1028,4 @@ } | ||
return year + 1 | ||
} else if (date.getTime() >= startOfThisYear.getTime()) { | ||
} | ||
if (date.getTime() >= startOfThisYear.getTime()) { | ||
return year | ||
@@ -1019,0 +1032,0 @@ } |
@@ -72,3 +72,3 @@ import type { ErrorData, ErrorObject } from '..' | ||
message || | ||
[`not deeply equal`, `expected: ${_stringify(expected)}`, `got : ${_stringify(actual)}`] | ||
['not deeply equal', `expected: ${_stringify(expected)}`, `got : ${_stringify(actual)}`] | ||
.filter(Boolean) | ||
@@ -126,2 +126,3 @@ .join('\n') | ||
export function _assertTypeOf<T>(v: any, expectedType: string, message?: string): asserts v is T { | ||
// biome-ignore lint/suspicious/useValidTypeof: ok | ||
if (typeof v !== expectedType) { | ||
@@ -128,0 +129,0 @@ const msg = message || `Expected typeof ${expectedType}, actual typeof: ${typeof v}` |
@@ -79,3 +79,3 @@ /// <reference lib="es2022" preserve="true" /> | ||
if (typeof globalThis.fetch !== 'function') { | ||
throw new TypeError(`globalThis.fetch is not available`) | ||
throw new TypeError('globalThis.fetch is not available') | ||
} | ||
@@ -381,3 +381,3 @@ | ||
// Error is to be handled upstream | ||
throw new Error(`fetchResponse.body is null`) | ||
throw new Error('fetchResponse.body is null') | ||
} | ||
@@ -539,3 +539,3 @@ } | ||
const date = new Date(retryAfterStr) | ||
if (!isNaN(date as any)) { | ||
if (!Number.isNaN(date as any)) { | ||
timeout = Number(date) - Date.now() | ||
@@ -547,3 +547,3 @@ } | ||
if (!timeout) { | ||
this.cfg.logger.warn(`retry-after could not be parsed`) | ||
this.cfg.logger.warn('retry-after could not be parsed') | ||
} | ||
@@ -582,3 +582,5 @@ } | ||
// should not retry on `unexpected redirect` in error.cause.cause | ||
if ((res.err?.cause as ErrorLike | void)?.cause?.message?.includes('unexpected redirect')) { | ||
if ( | ||
(res.err?.cause as ErrorLike | undefined)?.cause?.message?.includes('unexpected redirect') | ||
) { | ||
return false | ||
@@ -717,3 +719,3 @@ } | ||
if (req.fullUrl.startsWith('/')) { | ||
console.warn(`Fetcher: url should not start with / when baseUrl is specified`) | ||
console.warn('Fetcher: url should not start with / when baseUrl is specified') | ||
req.fullUrl = req.fullUrl.slice(1) | ||
@@ -720,0 +722,0 @@ } |
@@ -180,3 +180,3 @@ import { _uniq } from '../array/array.util' | ||
} else { | ||
delete this.schema.optionalField | ||
this.schema.optionalField = undefined | ||
} | ||
@@ -335,3 +335,3 @@ return this | ||
} else { | ||
delete schema.optionalField | ||
schema.optionalField = undefined | ||
} | ||
@@ -338,0 +338,0 @@ this.schema.properties[k] = schema |
@@ -0,1 +1,2 @@ | ||
import { _assert } from '../error/assert' | ||
import { _sortNumbers } from '../number/number.util' | ||
@@ -12,3 +13,6 @@ | ||
export function _average(values: number[]): number { | ||
return values.reduce((a, b) => a + b) / values.length | ||
_assert(values.length, '_average is called on empty array') | ||
let total = 0 | ||
for (const n of values) total += n | ||
return total / values.length | ||
} | ||
@@ -20,3 +24,3 @@ | ||
export function _averageOrNull(values: number[] | undefined | null): number | null { | ||
return values?.length ? values.reduce((a, b) => a + b) / values.length : null | ||
return values?.length ? _average(values) : null | ||
} | ||
@@ -28,6 +32,9 @@ | ||
export function _averageWeighted(values: number[], weights: number[]): number { | ||
const numerator = values.map((value, i) => value * weights[i]!).reduce((a, b) => a + b) | ||
const denominator = weights.reduce((a, b) => a + b) | ||
let numerator = 0 | ||
let denominator = 0 | ||
// eslint-disable-next-line unicorn/no-for-loop | ||
for (let i = 0; i < values.length; i++) { | ||
numerator += values[i]! * weights[i]! | ||
denominator += weights[i]! | ||
} | ||
return numerator / denominator | ||
@@ -34,0 +41,0 @@ } |
@@ -21,3 +21,5 @@ /** | ||
if (this.data.length === 0) return 0 | ||
return this.data.reduce((total, n) => total + n, 0) / this.data.length | ||
let total = 0 | ||
for (const n of this.data) total += n | ||
return total / this.data.length | ||
} | ||
@@ -24,0 +26,0 @@ |
@@ -10,3 +10,3 @@ /* eslint-disable no-bitwise */ | ||
let seed = 0x2f6e2b1 | ||
return function () { | ||
return () => { | ||
// Robert Jenkins’ 32 bit integer hash function | ||
@@ -13,0 +13,0 @@ seed = (seed + 0x7ed55d16 + (seed << 12)) & 0xffffffff |
@@ -49,5 +49,7 @@ import type { Inclusiveness, SortDirection } from '../types' | ||
return x >= min && x < max | ||
} else if (incl === '[]') { | ||
} | ||
if (incl === '[]') { | ||
return x >= min && x <= max | ||
} else if (incl === '(]') { | ||
} | ||
if (incl === '(]') { | ||
return x > min && x <= max | ||
@@ -54,0 +56,0 @@ } |
import { _isEmpty, _isObject } from '../is.util' | ||
import type { AnyObject, ObjectMapper, ObjectPredicate, ValueOf } from '../types' | ||
import { _objectEntries, KeyValueTuple, Reviver, SKIP } from '../types' | ||
import { | ||
_objectEntries, | ||
AnyObject, | ||
KeyValueTuple, | ||
ObjectMapper, | ||
ObjectPredicate, | ||
Reviver, | ||
SKIP, | ||
ValueOf, | ||
} from '../types' | ||
@@ -16,12 +24,13 @@ /** | ||
// Start as original object (mutable), DELETE properties that are not whitelisted | ||
return Object.keys(obj).reduce((r, prop) => { | ||
if (!props.includes(prop as K)) delete r[prop] | ||
return r | ||
}, obj) | ||
for (const prop of Object.keys(obj)) { | ||
if (!props.includes(prop as K)) delete obj[prop] | ||
} | ||
return obj | ||
} | ||
// Start as empty object, pick/add needed properties | ||
return props.reduce((r, prop) => { | ||
const r = {} as T | ||
for (const prop of props) { | ||
if (prop in obj) r[prop] = obj[prop] | ||
return r | ||
}, {} as T) | ||
} | ||
return r | ||
} | ||
@@ -38,9 +47,14 @@ | ||
): T { | ||
return props.reduce( | ||
(r, prop) => { | ||
delete r[prop] | ||
return r | ||
}, | ||
mutate ? obj : { ...obj }, | ||
) | ||
if (mutate) { | ||
for (const prop of props) { | ||
delete obj[prop] | ||
} | ||
return obj | ||
} | ||
const r = {} as T | ||
for (const prop of Object.keys(obj)) { | ||
if (!props.includes(prop as K)) r[prop as K] = obj[prop] | ||
} | ||
return r | ||
} | ||
@@ -57,9 +71,7 @@ | ||
export function _mask<T extends AnyObject>(obj: T, props: string[], mutate = false): T { | ||
return props.reduce( | ||
(r, prop) => { | ||
_unset(r, prop) | ||
return r | ||
}, | ||
mutate ? obj : _deepCopy(obj), | ||
) | ||
const r = mutate ? obj : _deepCopy(obj) | ||
for (const prop of props) { | ||
_unset(r, prop) | ||
} | ||
return r | ||
} | ||
@@ -102,9 +114,18 @@ | ||
): T { | ||
return Object.keys(obj).reduce( | ||
(r, k) => { | ||
if (!predicate(k as keyof T, r[k], obj)) delete r[k] | ||
return r | ||
}, | ||
mutate ? obj : { ...obj }, | ||
) | ||
if (mutate) { | ||
for (const [k, v] of _objectEntries(obj)) { | ||
if (!predicate(k, v, obj)) { | ||
delete obj[k] | ||
} | ||
} | ||
return obj | ||
} | ||
const r = {} as T | ||
for (const [k, v] of _objectEntries(obj)) { | ||
if (predicate(k, v, obj)) { | ||
r[k] = v | ||
} | ||
} | ||
return r | ||
} | ||
@@ -128,9 +149,7 @@ | ||
): OUT { | ||
return _objectEntries(obj).reduce( | ||
(map, [k, v]) => { | ||
map[k] = mapper(k, v, obj) | ||
return map | ||
}, | ||
mutate ? obj : ({} as IN), | ||
) as any | ||
const map: any = mutate ? obj : {} | ||
for (const [k, v] of Object.entries(obj)) { | ||
map[k] = mapper(k, v, obj) | ||
} | ||
return map | ||
} | ||
@@ -147,6 +166,7 @@ | ||
export function _mapKeys<T extends AnyObject>(obj: T, mapper: ObjectMapper<T, string>): T { | ||
return _objectEntries(obj).reduce((map, [k, v]) => { | ||
map[mapper(k, v, obj)] = v | ||
return map | ||
}, {} as AnyObject) as T | ||
const map = {} as T | ||
for (const [k, v] of Object.entries(obj)) { | ||
map[mapper(k, v, obj) as keyof T] = v | ||
} | ||
return map | ||
} | ||
@@ -174,9 +194,9 @@ | ||
): OUT { | ||
return Object.entries(obj).reduce((map, [k, v]) => { | ||
const map: any = {} | ||
for (const [k, v] of Object.entries(obj)) { | ||
const r = mapper(k, v, obj) | ||
if (r !== SKIP) { | ||
map[r[0]] = r[1] | ||
} | ||
return map | ||
}, {} as AnyObject) as OUT | ||
if (r === SKIP) continue | ||
map[r[0]] = r[1] | ||
} | ||
return map | ||
} | ||
@@ -272,3 +292,4 @@ | ||
return o.trim() as T | ||
} else if (typeof o === 'object') { | ||
} | ||
if (typeof o === 'object') { | ||
Object.keys(o).forEach(k => { | ||
@@ -332,6 +353,9 @@ o[k] = _deepTrim(o[k]) | ||
export function _get<T extends AnyObject>(obj = {} as T, path = ''): unknown { | ||
return path | ||
.replaceAll(/\[([^\]]+)]/g, '.$1') | ||
.split('.') | ||
.reduce((o, p) => o?.[p], obj) | ||
return ( | ||
path | ||
.replaceAll(/\[([^\]]+)]/g, '.$1') | ||
.split('.') | ||
// eslint-disable-next-line unicorn/no-array-reduce | ||
.reduce((o, p) => o?.[p], obj) | ||
) | ||
} | ||
@@ -363,2 +387,3 @@ | ||
// eslint-disable-next-line unicorn/no-array-reduce | ||
;(path as any[]).slice(0, -1).reduce( | ||
@@ -365,0 +390,0 @@ ( |
@@ -1,2 +0,2 @@ | ||
import type { PromisableFunction } from '../types' | ||
import type { NumberOfMilliseconds, PromisableFunction } from '../types' | ||
import { DeferredPromise, pDefer } from './pDefer' | ||
@@ -10,3 +10,3 @@ | ||
*/ | ||
export async function pDelay<T>(ms = 0, value?: T): Promise<T> { | ||
export async function pDelay<T>(ms: NumberOfMilliseconds = 0, value?: T): Promise<T> { | ||
return await new Promise<T>((resolve, reject) => | ||
@@ -28,3 +28,6 @@ setTimeout(value instanceof Error ? reject : resolve, ms, value), | ||
*/ | ||
export function pDelayFn<T>(ms = 0, fn: PromisableFunction<T>): DeferredPromise<T> { | ||
export function pDelayFn<T>( | ||
ms: NumberOfMilliseconds, | ||
fn: PromisableFunction<T>, | ||
): DeferredPromise<T> { | ||
const p = pDefer<T>() | ||
@@ -31,0 +34,0 @@ |
import { _range } from './array/range' | ||
import { _assert } from './error/assert' | ||
import { _isTruthy } from './is.util' | ||
import { SortDirection } from './types' | ||
@@ -89,3 +88,10 @@ | ||
maxOrUndefined(items: SemverInputNullable[]): Semver | undefined { | ||
return items.length ? this.max(items) : undefined | ||
let max: Semver | undefined | ||
for (const item of items) { | ||
const input = this.fromInputOrUndefined(item) | ||
if (!max || input?.isAfter(max)) { | ||
max = input | ||
} | ||
} | ||
return max | ||
} | ||
@@ -98,7 +104,5 @@ | ||
max(items: SemverInputNullable[]): Semver { | ||
const items2 = items.filter(_isTruthy) | ||
_assert(items2.length, 'semver.max called on empty array') | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((max, item) => (max.isSameOrAfter(item) ? max : item)) | ||
const max = this.maxOrUndefined(items) | ||
_assert(max, 'semver.max called on empty array') | ||
return max | ||
} | ||
@@ -110,3 +114,10 @@ | ||
minOrUndefined(items: SemverInputNullable[]): Semver | undefined { | ||
return items.length ? this.min(items) : undefined | ||
let min: Semver | undefined | ||
for (const item of items) { | ||
const input = this.fromInputOrUndefined(item) | ||
if (!min || input?.isBefore(min)) { | ||
min = input | ||
} | ||
} | ||
return min | ||
} | ||
@@ -119,7 +130,5 @@ | ||
min(items: SemverInputNullable[]): Semver { | ||
const items2 = items.filter(_isTruthy) | ||
_assert(items2.length, 'semver.min called on empty array') | ||
return items2 | ||
.map(i => this.fromInput(i)) | ||
.reduce((min, item) => (min.isSameOrBefore(item) ? min : item)) | ||
const min = this.minOrUndefined(items) | ||
_assert(min, 'semver.min called on empty array') | ||
return min | ||
} | ||
@@ -126,0 +135,0 @@ |
@@ -5,21 +5,24 @@ import { words } from './lodash/words' | ||
export function _camelCase(s: string): string { | ||
// return s.replace(/(_\w)/g, m => m[1]!.toUpperCase()) | ||
return words(s.replaceAll(/['\u2019]/g, '')).reduce((result, word, index) => { | ||
let r = '' | ||
for (let word of words(s.replaceAll(/['\u2019]/g, ''))) { | ||
word = word.toLowerCase() | ||
return result + (index ? _upperFirst(word) : word) | ||
}, '') | ||
r += r ? _upperFirst(word) : word | ||
} | ||
return r | ||
} | ||
export function _snakeCase(s: string): string { | ||
return words(s.replaceAll(/['\u2019]/g, '')).reduce( | ||
(result, word, index) => result + (index ? '_' : '') + word.toLowerCase(), | ||
'', | ||
) | ||
let r = '' | ||
for (const word of words(s.replaceAll(/['\u2019]/g, ''))) { | ||
r += (r ? '_' : '') + word.toLowerCase() | ||
} | ||
return r | ||
} | ||
export function _kebabCase(s: string): string { | ||
return words(s.replaceAll(/['\u2019]/g, '')).reduce( | ||
(result, word, index) => result + (index ? '-' : '') + word.toLowerCase(), | ||
'', | ||
) | ||
let r = '' | ||
for (const word of words(s.replaceAll(/['\u2019]/g, ''))) { | ||
r += (r ? '-' : '') + word.toLowerCase() | ||
} | ||
return r | ||
} |
@@ -57,3 +57,3 @@ const array: number[] = [] | ||
let bCharacterCode | ||
let bCharacterCode: number | ||
let result: number | ||
@@ -60,0 +60,0 @@ let temporary: number |
@@ -12,2 +12,3 @@ // from: https://github.com/lodash/lodash/blob/master/words.js | ||
/** Used to match words composed of alphanumeric characters. */ | ||
// biome-ignore lint/suspicious/noControlCharactersInRegex: ok | ||
const reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g | ||
@@ -14,0 +15,0 @@ |
@@ -29,3 +29,3 @@ import type { Reviver } from '../types' | ||
cycleReplacer ??= function (key, value) { | ||
cycleReplacer ??= (key, value) => { | ||
if (stack[0] === value) return '[Circular ~]' | ||
@@ -32,0 +32,0 @@ return '[Circular ~.' + keys.slice(0, stack.indexOf(value)).join('.') + ']' |
/** | ||
* Converts the first character of string to upper case and the remaining to lower case. | ||
*/ | ||
export function _capitalize(s: string = ''): string { | ||
export function _capitalize(s = ''): string { | ||
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase() | ||
} | ||
export function _upperFirst(s: string = ''): string { | ||
export function _upperFirst(s = ''): string { | ||
return s.charAt(0).toUpperCase() + s.slice(1) | ||
@@ -10,0 +10,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1074034
32571