nhb-toolbox 4.26.64 → 4.26.69
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/CHANGELOG.md +11 -0
- package/dist/cjs/date/Chronos.js +40 -47
- package/dist/dts/date/Chronos.d.ts +2 -2
- package/dist/dts/date/types.d.ts +3 -3
- package/dist/dts/object/sanitize.d.ts +4 -4
- package/dist/dts/object/types.d.ts +83 -4
- package/dist/dts/utils/types.d.ts +24 -7
- package/dist/esm/date/Chronos.js +40 -47
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,17 @@ All notable changes to the package will be documented here.
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [4.26.69] - 2025-11-18
|
|
10
|
+
|
|
11
|
+
- **Updated** *return type* of `sanitizeData` utility:
|
|
12
|
+
- **Fixed** *return type* when keys are ignored by *removing those keys* using `SanitizedData`, `OmitPath` and other new `type helpers`.
|
|
13
|
+
- **Fixed** the *return type* when it is called with `_return = 'partial'` parameter by *making all the nested properties optional*.
|
|
14
|
+
- **Created** new *utility type* `$DeepPartial` to satisfy this *return type*.
|
|
15
|
+
|
|
16
|
+
## [4.26.66] - 2025-11-17
|
|
17
|
+
|
|
18
|
+
- **Changed** the signature of `Chronos` `get()` method to `get<Unit extends TimeUnit>(unit: Unit): TimeUnitValue<Unit>` to align with `set()` method.
|
|
19
|
+
|
|
9
20
|
## [4.26.64] - 2025-11-17
|
|
10
21
|
|
|
11
22
|
### 🕧 Fixes in Chronos
|
package/dist/cjs/date/Chronos.js
CHANGED
|
@@ -60,22 +60,22 @@ class Chronos {
|
|
|
60
60
|
yield ['minute', this.minute];
|
|
61
61
|
yield ['second', this.second];
|
|
62
62
|
yield ['millisecond', this.millisecond];
|
|
63
|
-
yield ['timestamp', this.
|
|
63
|
+
yield ['timestamp', this.getTimeStamp()];
|
|
64
64
|
yield ['unix', this.unix];
|
|
65
65
|
}
|
|
66
66
|
[Symbol.toPrimitive](hint) {
|
|
67
67
|
if (hint === 'number')
|
|
68
|
-
return this.
|
|
68
|
+
return this.getTimeStamp();
|
|
69
69
|
return this.toLocalISOString();
|
|
70
70
|
}
|
|
71
71
|
[Symbol.replace](string, replacement) {
|
|
72
|
-
return string.replace(this.#removeUTCFromISO(
|
|
72
|
+
return string.replace(this.#removeUTCFromISO(), replacement);
|
|
73
73
|
}
|
|
74
74
|
[Symbol.search](string) {
|
|
75
|
-
return string.indexOf(this.#removeUTCFromISO(
|
|
75
|
+
return string.indexOf(this.#removeUTCFromISO());
|
|
76
76
|
}
|
|
77
77
|
[Symbol.split](string) {
|
|
78
|
-
return string.split(this.#removeUTCFromISO(
|
|
78
|
+
return string.split(this.#removeUTCFromISO());
|
|
79
79
|
}
|
|
80
80
|
[Symbol.match](string) {
|
|
81
81
|
const [datePart, timePart] = this.toLocalISOString().split('.')[0].split('T');
|
|
@@ -154,7 +154,6 @@ class Chronos {
|
|
|
154
154
|
const minutes = _getUnitValue('Minutes');
|
|
155
155
|
const seconds = _getUnitValue('Seconds');
|
|
156
156
|
const milliseconds = _getUnitValue('Milliseconds');
|
|
157
|
-
const timeZone = useUTC ? 'Z' : this.getTimeZoneOffset();
|
|
158
157
|
const dateComponents = {
|
|
159
158
|
YYYY: String(year),
|
|
160
159
|
YY: String(year).slice(-2),
|
|
@@ -182,7 +181,7 @@ class Chronos {
|
|
|
182
181
|
mss: String(milliseconds).padStart(3, '0'),
|
|
183
182
|
a: hours < 12 ? 'am' : 'pm',
|
|
184
183
|
A: hours < 12 ? 'AM' : 'PM',
|
|
185
|
-
ZZ:
|
|
184
|
+
ZZ: useUTC ? 'Z' : this.getTimeZoneOffset(),
|
|
186
185
|
};
|
|
187
186
|
const tokenRegex = new RegExp(`^(${constants_1.SORTED_TIME_FORMATS.join('|')})`);
|
|
188
187
|
let result = '';
|
|
@@ -208,10 +207,11 @@ class Chronos {
|
|
|
208
207
|
}
|
|
209
208
|
return result;
|
|
210
209
|
}
|
|
211
|
-
#removeUTCFromISO(local =
|
|
210
|
+
#removeUTCFromISO(local = true) {
|
|
211
|
+
const search = /\.\d+(Z|[+-]\d{2}:\d{2})?$/;
|
|
212
212
|
return local ?
|
|
213
|
-
this.toLocalISOString().replace(
|
|
214
|
-
: this.toISOString().replace(
|
|
213
|
+
this.toLocalISOString().replace(search, '')
|
|
214
|
+
: this.toISOString().replace(search, '');
|
|
215
215
|
}
|
|
216
216
|
get year() {
|
|
217
217
|
return this.#date.getFullYear();
|
|
@@ -269,7 +269,7 @@ class Chronos {
|
|
|
269
269
|
const targetOffset = (0, utils_1.extractMinutesFromUTC)(this.#offset);
|
|
270
270
|
const systemOffset = this.getUTCOffsetMinutes();
|
|
271
271
|
const adjustmentMs = (targetOffset - systemOffset) * 60_000;
|
|
272
|
-
return new Date(this.#
|
|
272
|
+
return new Date(this.#timestamp - adjustmentMs);
|
|
273
273
|
}
|
|
274
274
|
toString() {
|
|
275
275
|
return this.#format('dd mmm DD YYYY HH:mm:ss ')
|
|
@@ -322,31 +322,25 @@ class Chronos {
|
|
|
322
322
|
return (0, guards_1.isLeapYear)(year ?? this.year);
|
|
323
323
|
}
|
|
324
324
|
isEqual(other) {
|
|
325
|
-
|
|
326
|
-
return this.#timestamp === time.#timestamp;
|
|
325
|
+
return this.#timestamp === _a.#cast(other).#timestamp;
|
|
327
326
|
}
|
|
328
327
|
isEqualOrBefore(other) {
|
|
329
|
-
|
|
330
|
-
return this.#timestamp <= time.#timestamp;
|
|
328
|
+
return this.#timestamp <= _a.#cast(other).#timestamp;
|
|
331
329
|
}
|
|
332
330
|
isEqualOrAfter(other) {
|
|
333
|
-
|
|
334
|
-
return this.#timestamp >= time.#timestamp;
|
|
331
|
+
return this.#timestamp >= _a.#cast(other).#timestamp;
|
|
335
332
|
}
|
|
336
333
|
isSame(other, unit, weekStartsOn = 0) {
|
|
337
|
-
const time = _a.#cast(other);
|
|
338
334
|
return (this.startOf(unit, weekStartsOn).#timestamp ===
|
|
339
|
-
|
|
335
|
+
_a.#cast(other).startOf(unit, weekStartsOn).#timestamp);
|
|
340
336
|
}
|
|
341
337
|
isBefore(other, unit, weekStartsOn = 0) {
|
|
342
|
-
const time = _a.#cast(other);
|
|
343
338
|
return (this.startOf(unit, weekStartsOn).#timestamp <
|
|
344
|
-
|
|
339
|
+
_a.#cast(other).startOf(unit, weekStartsOn).#timestamp);
|
|
345
340
|
}
|
|
346
341
|
isAfter(other, unit, weekStartsOn = 0) {
|
|
347
|
-
const time = _a.#cast(other);
|
|
348
342
|
return (this.startOf(unit, weekStartsOn).#timestamp >
|
|
349
|
-
|
|
343
|
+
_a.#cast(other).startOf(unit, weekStartsOn).#timestamp);
|
|
350
344
|
}
|
|
351
345
|
isSameOrBefore(other, unit, weekStartsOn = 0) {
|
|
352
346
|
return (this.isSame(other, unit, weekStartsOn) || this.isBefore(other, unit, weekStartsOn));
|
|
@@ -355,9 +349,9 @@ class Chronos {
|
|
|
355
349
|
return (this.isSame(other, unit, weekStartsOn) || this.isAfter(other, unit, weekStartsOn));
|
|
356
350
|
}
|
|
357
351
|
isBetween(start, end, inclusive = '()') {
|
|
358
|
-
const s =
|
|
359
|
-
const e =
|
|
360
|
-
const t = this.
|
|
352
|
+
const s = _a.#cast(start).getTimeStamp();
|
|
353
|
+
const e = _a.#cast(end).getTimeStamp();
|
|
354
|
+
const t = this.getTimeStamp();
|
|
361
355
|
switch (inclusive) {
|
|
362
356
|
case '[]':
|
|
363
357
|
return t >= s && t <= e;
|
|
@@ -466,21 +460,21 @@ class Chronos {
|
|
|
466
460
|
get(unit) {
|
|
467
461
|
switch (unit) {
|
|
468
462
|
case 'year':
|
|
469
|
-
return this
|
|
463
|
+
return this.year;
|
|
470
464
|
case 'month':
|
|
471
|
-
return this
|
|
465
|
+
return this.isoMonth;
|
|
472
466
|
case 'day':
|
|
473
|
-
return this
|
|
467
|
+
return this.date;
|
|
474
468
|
case 'week':
|
|
475
469
|
return this.getWeek();
|
|
476
470
|
case 'hour':
|
|
477
|
-
return this
|
|
471
|
+
return this.hour;
|
|
478
472
|
case 'minute':
|
|
479
|
-
return this
|
|
473
|
+
return this.minute;
|
|
480
474
|
case 'second':
|
|
481
|
-
return this
|
|
475
|
+
return this.second;
|
|
482
476
|
case 'millisecond':
|
|
483
|
-
return this
|
|
477
|
+
return this.millisecond;
|
|
484
478
|
}
|
|
485
479
|
}
|
|
486
480
|
set(unit, value) {
|
|
@@ -514,7 +508,7 @@ class Chronos {
|
|
|
514
508
|
}
|
|
515
509
|
diff(other, unit) {
|
|
516
510
|
const time = _a.#cast(other);
|
|
517
|
-
const msDiff = this.#
|
|
511
|
+
const msDiff = this.#timestamp - time.#timestamp;
|
|
518
512
|
switch (unit) {
|
|
519
513
|
case 'millisecond':
|
|
520
514
|
return msDiff;
|
|
@@ -540,7 +534,7 @@ class Chronos {
|
|
|
540
534
|
}
|
|
541
535
|
}
|
|
542
536
|
calendar(baseDate) {
|
|
543
|
-
const base = baseDate ?
|
|
537
|
+
const base = baseDate ? _a.#cast(baseDate) : new _a();
|
|
544
538
|
const input = this.startOf('day');
|
|
545
539
|
const comparison = base.startOf('day');
|
|
546
540
|
const diff = input.diff(comparison, 'day');
|
|
@@ -651,12 +645,12 @@ class Chronos {
|
|
|
651
645
|
}
|
|
652
646
|
toUTC() {
|
|
653
647
|
const offset = this.getTimeZoneOffsetMinutes();
|
|
654
|
-
const utc = new Date(this.#
|
|
648
|
+
const utc = new Date(this.#timestamp - offset * 60 * 1000);
|
|
655
649
|
return new _a(utc).#withOrigin('toUTC', 'UTC+00:00', 'Greenwich Mean Time', 'UTC');
|
|
656
650
|
}
|
|
657
651
|
toLocal() {
|
|
658
652
|
const offset = this.getTimeZoneOffsetMinutes() - this.getUTCOffsetMinutes();
|
|
659
|
-
const localTime = new Date(this.#
|
|
653
|
+
const localTime = new Date(this.#timestamp - offset * 60 * 1000);
|
|
660
654
|
return new _a(localTime).#withOrigin('toLocal');
|
|
661
655
|
}
|
|
662
656
|
day(index) {
|
|
@@ -671,10 +665,10 @@ class Chronos {
|
|
|
671
665
|
if (options) {
|
|
672
666
|
if ('from' in options || 'to' in options) {
|
|
673
667
|
if (options?.from) {
|
|
674
|
-
startDate =
|
|
668
|
+
startDate = _a.#cast(options?.from);
|
|
675
669
|
}
|
|
676
670
|
if (options?.to) {
|
|
677
|
-
endDate =
|
|
671
|
+
endDate = _a.#cast(options?.to);
|
|
678
672
|
}
|
|
679
673
|
}
|
|
680
674
|
else if ('span' in options || 'unit' in options) {
|
|
@@ -771,8 +765,7 @@ class Chronos {
|
|
|
771
765
|
}
|
|
772
766
|
static today(options) {
|
|
773
767
|
const { format = 'dd, mmm DD, YYYY HH:mm:ss', useUTC = false } = options || {};
|
|
774
|
-
|
|
775
|
-
return new _a(today).#format(format, useUTC);
|
|
768
|
+
return new _a().#format(format, useUTC);
|
|
776
769
|
}
|
|
777
770
|
static yesterday() {
|
|
778
771
|
const today = new Date();
|
|
@@ -790,7 +783,7 @@ class Chronos {
|
|
|
790
783
|
static utc(dateLike) {
|
|
791
784
|
const chronos = new _a(dateLike);
|
|
792
785
|
const offset = chronos.getTimeZoneOffsetMinutes();
|
|
793
|
-
const utc = new Date(chronos.#
|
|
786
|
+
const utc = new Date(chronos.#timestamp - offset * 60 * 1000);
|
|
794
787
|
return new _a(utc).#withOrigin('utc', 'UTC+00:00', 'Greenwich Mean Time', 'UTC');
|
|
795
788
|
}
|
|
796
789
|
static formatTimePart(time, format) {
|
|
@@ -806,10 +799,10 @@ class Chronos {
|
|
|
806
799
|
if (options) {
|
|
807
800
|
if ('from' in options || 'to' in options) {
|
|
808
801
|
if (options?.from) {
|
|
809
|
-
startDate =
|
|
802
|
+
startDate = _a.#cast(options?.from);
|
|
810
803
|
}
|
|
811
804
|
if (options?.to) {
|
|
812
|
-
endDate =
|
|
805
|
+
endDate = _a.#cast(options?.to);
|
|
813
806
|
}
|
|
814
807
|
}
|
|
815
808
|
else if ('span' in options || 'unit' in options) {
|
|
@@ -834,7 +827,7 @@ class Chronos {
|
|
|
834
827
|
let winner = _a.#cast(dates[0]);
|
|
835
828
|
for (const d of dates) {
|
|
836
829
|
const c = _a.#cast(d);
|
|
837
|
-
if (c.
|
|
830
|
+
if (c.getTimeStamp() < winner.getTimeStamp()) {
|
|
838
831
|
winner = c;
|
|
839
832
|
}
|
|
840
833
|
}
|
|
@@ -844,7 +837,7 @@ class Chronos {
|
|
|
844
837
|
let winner = _a.#cast(dates[0]);
|
|
845
838
|
for (const d of dates) {
|
|
846
839
|
const c = _a.#cast(d);
|
|
847
|
-
if (c.
|
|
840
|
+
if (c.getTimeStamp() > winner.getTimeStamp()) {
|
|
848
841
|
winner = c;
|
|
849
842
|
}
|
|
850
843
|
}
|
|
@@ -861,7 +854,7 @@ class Chronos {
|
|
|
861
854
|
}
|
|
862
855
|
}
|
|
863
856
|
else {
|
|
864
|
-
year =
|
|
857
|
+
year = _a.#cast(date).year;
|
|
865
858
|
}
|
|
866
859
|
return (0, guards_1.isLeapYear)(year);
|
|
867
860
|
}
|
|
@@ -418,9 +418,9 @@ export declare class Chronos {
|
|
|
418
418
|
subtract(number: number, unit: TimeUnit): Chronos;
|
|
419
419
|
/**
|
|
420
420
|
* @instance Gets the value of a specific time unit from the date.
|
|
421
|
-
* @param unit The unit to retrieve.
|
|
421
|
+
* @param unit The unit to retrieve. Type of return value is determined by `unit`.
|
|
422
422
|
*/
|
|
423
|
-
get(unit:
|
|
423
|
+
get<Unit extends TimeUnit>(unit: Unit): TimeUnitValue<Unit>;
|
|
424
424
|
/**
|
|
425
425
|
* @instance Returns a new `Chronos` instance with the specified unit set to the given value.
|
|
426
426
|
* @param unit The unit to modify. Type of `value` is determined by `unit`.
|
package/dist/dts/date/types.d.ts
CHANGED
|
@@ -82,7 +82,7 @@ export type Second = (typeof SECOND_FORMATS)[number];
|
|
|
82
82
|
export type Millisecond = (typeof MILLISECOND_FORMATS)[number];
|
|
83
83
|
/** Time formats in either capital or lowercase `am/pm` format */
|
|
84
84
|
export type TimeFormats = (typeof TIME_FORMATS)[number];
|
|
85
|
-
/** Represents a
|
|
85
|
+
/** Represents a unit suffix for {@link Date} getter methods (e.g., `'FullYear'` in `'getFullYear'`, `'Month'` in `'getMonth'` etc.). */
|
|
86
86
|
export type $DateUnit = 'FullYear' | 'Month' | 'Day' | 'Date' | 'Hours' | 'Minutes' | 'Seconds' | 'Milliseconds';
|
|
87
87
|
/** Standard union formats for `Chronos`. */
|
|
88
88
|
export type ChronosFormat = Year | Month | Day | MonthDate | Hour | Minute | Second | Millisecond | TimeFormats | 'ZZ';
|
|
@@ -314,7 +314,7 @@ export interface RelativeRangeOptions {
|
|
|
314
314
|
span?: number;
|
|
315
315
|
/** - Unit of time to advance the date range. Defaults to `'week'`. Controlled by the `span` option. */
|
|
316
316
|
unit?: 'year' | 'month' | 'week' | 'day';
|
|
317
|
-
/** - Output format
|
|
317
|
+
/** - Output format: return as local ISO string or UTC ISO string. Defaults to `'local'`. */
|
|
318
318
|
format?: 'local' | 'utc';
|
|
319
319
|
/** Whether to round the dates in the range to the start of the day. Default is `false`. */
|
|
320
320
|
roundDate?: boolean;
|
|
@@ -358,7 +358,7 @@ export interface RelativeDateRange {
|
|
|
358
358
|
span?: number;
|
|
359
359
|
/** - Unit of time to advance the date range. Defaults to `'week'`. Controlled by the `span` option. */
|
|
360
360
|
unit?: 'year' | 'month' | 'week' | 'day';
|
|
361
|
-
/** - Output format
|
|
361
|
+
/** - Output format: return as local ISO string or UTC ISO string. Defaults to `'local'`. */
|
|
362
362
|
format?: 'local' | 'utc';
|
|
363
363
|
/**
|
|
364
364
|
* An array of weekdays to exclude from the date range.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Any,
|
|
2
|
-
import type { GenericObject, SanitizeOptions } from './types';
|
|
1
|
+
import type { Any, PartialOrRequired } from '../types/index';
|
|
2
|
+
import type { DotNotationKey, GenericObject, SanitizedData, SanitizeOptions } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* * Trims all the words in a string.
|
|
5
5
|
*
|
|
@@ -23,7 +23,7 @@ export declare function sanitizeData(input: string[]): string[];
|
|
|
23
23
|
* @param _return - By default return type is as it is, passing this parameter `true` makes the return type `Partial<T>`.
|
|
24
24
|
* @returns A new object with the specified modifications.
|
|
25
25
|
*/
|
|
26
|
-
export declare function sanitizeData<
|
|
26
|
+
export declare function sanitizeData<Data extends GenericObject, Ignored extends DotNotationKey<Data> = never, PoR extends PartialOrRequired = 'required'>(object: Data, options?: SanitizeOptions<Data, Ignored>, _return?: PoR): SanitizedData<Data, Ignored, PoR>;
|
|
27
27
|
/**
|
|
28
28
|
* * Sanitizes a deeply nested array that may contain arrays, objects or other (mixed) data types.
|
|
29
29
|
* * Preserves structure while removing empty values and trimming strings and other operations.
|
|
@@ -33,7 +33,7 @@ export declare function sanitizeData<T extends GenericObject, B extends PartialO
|
|
|
33
33
|
* @param _return - By default return type is as it is, passing this parameter `partial` makes the return type `Partial<T>`.
|
|
34
34
|
* @returns A new sanitized array with the specified modifications.
|
|
35
35
|
*/
|
|
36
|
-
export declare function sanitizeData<
|
|
36
|
+
export declare function sanitizeData<Data extends GenericObject, Ignored extends DotNotationKey<Data> = never, PoR extends PartialOrRequired = 'required'>(array: Data[], options?: SanitizeOptions<Data, Ignored>, _return?: PoR): Array<SanitizedData<Data, Ignored, PoR>>;
|
|
37
37
|
/**
|
|
38
38
|
* * Parse an object of stringified values into their appropriate primitive types.
|
|
39
39
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AdvancedTypes, NormalPrimitive, ValidArray } from '../types/index';
|
|
2
|
-
import type { $UnionToIntersection, Prettify, Split, Tuple } from '../utils/types';
|
|
1
|
+
import type { AdvancedTypes, NormalPrimitive, PartialOrRequired, ValidArray } from '../types/index';
|
|
2
|
+
import type { $DeepPartial, $UnionToIntersection, Prettify, Split, Tuple } from '../utils/types';
|
|
3
3
|
import type { COUNTRIES } from './countries';
|
|
4
4
|
/** - Generic object with `unknown` value */
|
|
5
5
|
export type StrictObject = Record<string, unknown>;
|
|
@@ -103,13 +103,13 @@ export type DeepKeys<T extends GenericObject> = T extends AdvancedTypes ? never
|
|
|
103
103
|
/** - Converts the union of keys from {@link DeepKeys<T>} into a tuple. */
|
|
104
104
|
export type DeepKeysTuple<T extends GenericObject> = Tuple<DeepKeys<T>>;
|
|
105
105
|
/** - Options for `sanitizeData` utility. */
|
|
106
|
-
export interface SanitizeOptions<T
|
|
106
|
+
export interface SanitizeOptions<T, Ignored extends DotNotationKey<T>> {
|
|
107
107
|
/**
|
|
108
108
|
* An array of dot-notation keys to exclude from the sanitized output.
|
|
109
109
|
* This is only applicable when sanitizing plain objects or arrays of objects.
|
|
110
110
|
* When applied to nested or irregular array structures, behavior may be inconsistent or partially ignored.
|
|
111
111
|
*/
|
|
112
|
-
keysToIgnore?:
|
|
112
|
+
keysToIgnore?: Ignored[];
|
|
113
113
|
/** Whether to trim string values. Defaults to `true`. */
|
|
114
114
|
trimStrings?: boolean;
|
|
115
115
|
/** Whether to exclude nullish (`null` or `undefined`) values. Defaults to `false`. */
|
|
@@ -125,6 +125,85 @@ export interface SanitizeOptions<T> {
|
|
|
125
125
|
*/
|
|
126
126
|
requiredKeys?: '*' | DotNotationKey<T>[];
|
|
127
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* * Produces sanitized output data by omitting keys in `keysToIgnore` from {@link SanitizeOptions} and optionally applying partial deep nesting based on `_return` parameter.
|
|
130
|
+
*
|
|
131
|
+
* @remarks
|
|
132
|
+
* - When `PoR` is `'partial'`, all nested properties become optional after path omission.
|
|
133
|
+
* - When `PoR` is `'required'`, the resulting type keeps full property requirements.
|
|
134
|
+
* - Intended for return type of `sanitizeData` utility.
|
|
135
|
+
*/
|
|
136
|
+
export type SanitizedData<Data extends GenericObject, Ignored extends DotNotationKey<Data>, PoR extends PartialOrRequired> = PoR extends 'partial' ? $DeepPartial<OmitPath<Data, Ignored>> : OmitPath<Data, Ignored>;
|
|
137
|
+
/**
|
|
138
|
+
* * Extracts only the string keys from an object type.
|
|
139
|
+
*
|
|
140
|
+
* @remarks
|
|
141
|
+
* - Useful when iterating over object keys inside template-literal-based utility types,
|
|
142
|
+
* because TypeScript may include `symbol` keys in `keyof T`, which cannot be used in
|
|
143
|
+
* template literal types.
|
|
144
|
+
* - By filtering to `string`, all keys become safe for path operations.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* type A = { a: number; b: string; 1: boolean; [Symbol.iterator]: () => void };
|
|
148
|
+
* type Keys = ExtractStringKey<A>;
|
|
149
|
+
* // Result: "a" | "b"
|
|
150
|
+
*/
|
|
151
|
+
export type ExtractStringKey<T> = Extract<keyof T, string>;
|
|
152
|
+
/**
|
|
153
|
+
* * Joins a parent key and a child key into a dot-notation path.
|
|
154
|
+
*
|
|
155
|
+
* @remarks
|
|
156
|
+
* - If the parent path is an empty string, the child key is returned as-is.
|
|
157
|
+
* - Otherwise, the function produces `"parent.child"` formatting.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* type A = $JoinDotKey<'', 'user'>; // "user"
|
|
161
|
+
* type B = $JoinDotKey<'settings', 'theme'>; // "settings.theme"
|
|
162
|
+
*/
|
|
163
|
+
export type $JoinDotKey<Parent extends string, Key extends string> = Parent extends '' ? Key : `${Parent}.${Key}`;
|
|
164
|
+
/**
|
|
165
|
+
* * Checks whether a dot-notation path starts with the specified prefix.
|
|
166
|
+
*
|
|
167
|
+
* @remarks
|
|
168
|
+
* A path is considered a match if it is **exactly equal** to the prefix, or begins with `"prefix."`.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* type A = $DoesPathStartWith<'settings.timeout', 'settings'>; // true
|
|
172
|
+
* type B = $DoesPathStartWith<'settings', 'settings'>; // true
|
|
173
|
+
* type C = $DoesPathStartWith<'user.name', 'settings'>; // false
|
|
174
|
+
*/
|
|
175
|
+
export type $DoesPathStartWith<Path extends string, Prefix extends string> = Path extends Prefix | `${Prefix}.${string}` ? true : false;
|
|
176
|
+
/** Recursive utility that removes a specific dot-notation path from an object. */
|
|
177
|
+
type $OmitPath<T extends GenericObject, I extends string, P extends string = ''> = Prettify<{
|
|
178
|
+
[K in ExtractStringKey<T> as $DoesPathStartWith<$JoinDotKey<P, K>, I> extends true ? never : K]: T[K] extends GenericObject ? T[K] extends AdvancedTypes ? T[K] : $OmitPath<T[K], I, $JoinDotKey<P, K>> : T[K];
|
|
179
|
+
}>;
|
|
180
|
+
/**
|
|
181
|
+
* * Removes a dot-notation path from an object type while preserving its original shape.
|
|
182
|
+
*
|
|
183
|
+
* @remarks
|
|
184
|
+
* - It excludes the specified dot path, but **retains the full structure** of the parent object.
|
|
185
|
+
* - Only the targeted property is removed.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* type Input = {
|
|
189
|
+
* settings: {
|
|
190
|
+
* timeout: number;
|
|
191
|
+
* theme: string;
|
|
192
|
+
* };
|
|
193
|
+
* version: string;
|
|
194
|
+
* };
|
|
195
|
+
*
|
|
196
|
+
* type Clean = OmitPath<Input, "settings.timeout">;
|
|
197
|
+
*
|
|
198
|
+
* // Result:
|
|
199
|
+
* // {
|
|
200
|
+
* // settings: {
|
|
201
|
+
* // theme: string;
|
|
202
|
+
* // };
|
|
203
|
+
* // version: string;
|
|
204
|
+
* // }
|
|
205
|
+
*/
|
|
206
|
+
export type OmitPath<Object extends GenericObject, Ignored extends DotNotationKey<Object>> = $OmitPath<Object, Ignored>;
|
|
128
207
|
/** Options for `convertObjectValues` utility */
|
|
129
208
|
export interface ConvertObjectOptions<T extends GenericObject, Key extends NumericDotKey<T>, C extends 'string' | 'number'> {
|
|
130
209
|
/** Array of keys (properties) to convert to `number` or `string` */
|
|
@@ -75,28 +75,45 @@ export type KeysOfUnion<T> = T extends T ? keyof T : never;
|
|
|
75
75
|
* * Recursively makes all potential standard js object properties optional.
|
|
76
76
|
*
|
|
77
77
|
* @remarks
|
|
78
|
-
* - It excludes complex types like `Array`, `Map`, `File`, `Date`, `Chronos` etc. from being recursively partial.
|
|
79
|
-
* - Please, refer to {@link AdvancedTypes} to
|
|
78
|
+
* - It excludes keys of complex types like `Array`, `Map`, `File`, `Date`, `Chronos` etc. from being recursively partial.
|
|
79
|
+
* - Please, refer to {@link AdvancedTypes} to allow these complex types.
|
|
80
|
+
* - Also refer to {@link $DeepPartial} for less strict version.
|
|
80
81
|
*
|
|
81
82
|
* @example
|
|
82
83
|
* type Config = { a: string; nested: { b: number } };
|
|
83
84
|
* type PartialConfig = DeepPartial<Config>;
|
|
84
85
|
* // { a?: string; nested?: { b?: number } }
|
|
85
86
|
*/
|
|
86
|
-
export type DeepPartial<T> = {
|
|
87
|
+
export type DeepPartial<T> = Prettify<{
|
|
87
88
|
[K in keyof T]?: T[K] extends AdvancedTypes ? T[K] : T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
88
|
-
}
|
|
89
|
+
}>;
|
|
90
|
+
/**
|
|
91
|
+
* * Recursively makes all potential standard js object (also object in array) properties optional.
|
|
92
|
+
*
|
|
93
|
+
* @remarks
|
|
94
|
+
* - It excludes keys of complex types like `Map`, `File`, `Date`, `Chronos` etc. from being recursively partial.
|
|
95
|
+
* - Please, refer to {@link AdvancedTypes} to allow these complex types.
|
|
96
|
+
* - Also refer to {@link DeepPartial} for more strict version.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* type Config = { a: string; nested: { b: number }[] };
|
|
100
|
+
* type PartialConfig = $DeepPartial<Config>;
|
|
101
|
+
* // { a?: string; nested?: { b?: number; }[]; }
|
|
102
|
+
*/
|
|
103
|
+
export type $DeepPartial<T> = Prettify<{
|
|
104
|
+
[K in keyof T]?: T[K] extends Array<infer El> ? Array<$DeepPartial<El>> : T[K] extends AdvancedTypes ? T[K] : $DeepPartial<T[K]>;
|
|
105
|
+
}>;
|
|
89
106
|
/**
|
|
90
107
|
* * Recursively makes all properties in any object or array type optional.
|
|
91
108
|
*
|
|
92
109
|
* @example
|
|
93
110
|
* type Config = { a: string; nested: { b: number } };
|
|
94
|
-
* type PartialConfig =
|
|
111
|
+
* type PartialConfig = DeepPartialAll<Config>;
|
|
95
112
|
* // { a?: string; nested?: { b?: number } }
|
|
96
113
|
*/
|
|
97
|
-
export type DeepPartialAll<T> = T extends Array<infer El> ? Array<DeepPartialAll<El>> : {
|
|
114
|
+
export type DeepPartialAll<T> = T extends Array<infer El> ? Array<DeepPartialAll<El>> : Prettify<{
|
|
98
115
|
[K in keyof T]?: DeepPartialAll<T[K]>;
|
|
99
|
-
}
|
|
116
|
+
}>;
|
|
100
117
|
/**
|
|
101
118
|
* * Removes `readonly` modifiers from all properties of an object type.
|
|
102
119
|
*
|
package/dist/esm/date/Chronos.js
CHANGED
|
@@ -57,22 +57,22 @@ export class Chronos {
|
|
|
57
57
|
yield ['minute', this.minute];
|
|
58
58
|
yield ['second', this.second];
|
|
59
59
|
yield ['millisecond', this.millisecond];
|
|
60
|
-
yield ['timestamp', this.
|
|
60
|
+
yield ['timestamp', this.getTimeStamp()];
|
|
61
61
|
yield ['unix', this.unix];
|
|
62
62
|
}
|
|
63
63
|
[Symbol.toPrimitive](hint) {
|
|
64
64
|
if (hint === 'number')
|
|
65
|
-
return this.
|
|
65
|
+
return this.getTimeStamp();
|
|
66
66
|
return this.toLocalISOString();
|
|
67
67
|
}
|
|
68
68
|
[Symbol.replace](string, replacement) {
|
|
69
|
-
return string.replace(this.#removeUTCFromISO(
|
|
69
|
+
return string.replace(this.#removeUTCFromISO(), replacement);
|
|
70
70
|
}
|
|
71
71
|
[Symbol.search](string) {
|
|
72
|
-
return string.indexOf(this.#removeUTCFromISO(
|
|
72
|
+
return string.indexOf(this.#removeUTCFromISO());
|
|
73
73
|
}
|
|
74
74
|
[Symbol.split](string) {
|
|
75
|
-
return string.split(this.#removeUTCFromISO(
|
|
75
|
+
return string.split(this.#removeUTCFromISO());
|
|
76
76
|
}
|
|
77
77
|
[Symbol.match](string) {
|
|
78
78
|
const [datePart, timePart] = this.toLocalISOString().split('.')[0].split('T');
|
|
@@ -151,7 +151,6 @@ export class Chronos {
|
|
|
151
151
|
const minutes = _getUnitValue('Minutes');
|
|
152
152
|
const seconds = _getUnitValue('Seconds');
|
|
153
153
|
const milliseconds = _getUnitValue('Milliseconds');
|
|
154
|
-
const timeZone = useUTC ? 'Z' : this.getTimeZoneOffset();
|
|
155
154
|
const dateComponents = {
|
|
156
155
|
YYYY: String(year),
|
|
157
156
|
YY: String(year).slice(-2),
|
|
@@ -179,7 +178,7 @@ export class Chronos {
|
|
|
179
178
|
mss: String(milliseconds).padStart(3, '0'),
|
|
180
179
|
a: hours < 12 ? 'am' : 'pm',
|
|
181
180
|
A: hours < 12 ? 'AM' : 'PM',
|
|
182
|
-
ZZ:
|
|
181
|
+
ZZ: useUTC ? 'Z' : this.getTimeZoneOffset(),
|
|
183
182
|
};
|
|
184
183
|
const tokenRegex = new RegExp(`^(${SORTED_TIME_FORMATS.join('|')})`);
|
|
185
184
|
let result = '';
|
|
@@ -205,10 +204,11 @@ export class Chronos {
|
|
|
205
204
|
}
|
|
206
205
|
return result;
|
|
207
206
|
}
|
|
208
|
-
#removeUTCFromISO(local =
|
|
207
|
+
#removeUTCFromISO(local = true) {
|
|
208
|
+
const search = /\.\d+(Z|[+-]\d{2}:\d{2})?$/;
|
|
209
209
|
return local ?
|
|
210
|
-
this.toLocalISOString().replace(
|
|
211
|
-
: this.toISOString().replace(
|
|
210
|
+
this.toLocalISOString().replace(search, '')
|
|
211
|
+
: this.toISOString().replace(search, '');
|
|
212
212
|
}
|
|
213
213
|
get year() {
|
|
214
214
|
return this.#date.getFullYear();
|
|
@@ -266,7 +266,7 @@ export class Chronos {
|
|
|
266
266
|
const targetOffset = extractMinutesFromUTC(this.#offset);
|
|
267
267
|
const systemOffset = this.getUTCOffsetMinutes();
|
|
268
268
|
const adjustmentMs = (targetOffset - systemOffset) * 60_000;
|
|
269
|
-
return new Date(this.#
|
|
269
|
+
return new Date(this.#timestamp - adjustmentMs);
|
|
270
270
|
}
|
|
271
271
|
toString() {
|
|
272
272
|
return this.#format('dd mmm DD YYYY HH:mm:ss ')
|
|
@@ -319,31 +319,25 @@ export class Chronos {
|
|
|
319
319
|
return isLeapYear(year ?? this.year);
|
|
320
320
|
}
|
|
321
321
|
isEqual(other) {
|
|
322
|
-
|
|
323
|
-
return this.#timestamp === time.#timestamp;
|
|
322
|
+
return this.#timestamp === _a.#cast(other).#timestamp;
|
|
324
323
|
}
|
|
325
324
|
isEqualOrBefore(other) {
|
|
326
|
-
|
|
327
|
-
return this.#timestamp <= time.#timestamp;
|
|
325
|
+
return this.#timestamp <= _a.#cast(other).#timestamp;
|
|
328
326
|
}
|
|
329
327
|
isEqualOrAfter(other) {
|
|
330
|
-
|
|
331
|
-
return this.#timestamp >= time.#timestamp;
|
|
328
|
+
return this.#timestamp >= _a.#cast(other).#timestamp;
|
|
332
329
|
}
|
|
333
330
|
isSame(other, unit, weekStartsOn = 0) {
|
|
334
|
-
const time = _a.#cast(other);
|
|
335
331
|
return (this.startOf(unit, weekStartsOn).#timestamp ===
|
|
336
|
-
|
|
332
|
+
_a.#cast(other).startOf(unit, weekStartsOn).#timestamp);
|
|
337
333
|
}
|
|
338
334
|
isBefore(other, unit, weekStartsOn = 0) {
|
|
339
|
-
const time = _a.#cast(other);
|
|
340
335
|
return (this.startOf(unit, weekStartsOn).#timestamp <
|
|
341
|
-
|
|
336
|
+
_a.#cast(other).startOf(unit, weekStartsOn).#timestamp);
|
|
342
337
|
}
|
|
343
338
|
isAfter(other, unit, weekStartsOn = 0) {
|
|
344
|
-
const time = _a.#cast(other);
|
|
345
339
|
return (this.startOf(unit, weekStartsOn).#timestamp >
|
|
346
|
-
|
|
340
|
+
_a.#cast(other).startOf(unit, weekStartsOn).#timestamp);
|
|
347
341
|
}
|
|
348
342
|
isSameOrBefore(other, unit, weekStartsOn = 0) {
|
|
349
343
|
return (this.isSame(other, unit, weekStartsOn) || this.isBefore(other, unit, weekStartsOn));
|
|
@@ -352,9 +346,9 @@ export class Chronos {
|
|
|
352
346
|
return (this.isSame(other, unit, weekStartsOn) || this.isAfter(other, unit, weekStartsOn));
|
|
353
347
|
}
|
|
354
348
|
isBetween(start, end, inclusive = '()') {
|
|
355
|
-
const s =
|
|
356
|
-
const e =
|
|
357
|
-
const t = this.
|
|
349
|
+
const s = _a.#cast(start).getTimeStamp();
|
|
350
|
+
const e = _a.#cast(end).getTimeStamp();
|
|
351
|
+
const t = this.getTimeStamp();
|
|
358
352
|
switch (inclusive) {
|
|
359
353
|
case '[]':
|
|
360
354
|
return t >= s && t <= e;
|
|
@@ -463,21 +457,21 @@ export class Chronos {
|
|
|
463
457
|
get(unit) {
|
|
464
458
|
switch (unit) {
|
|
465
459
|
case 'year':
|
|
466
|
-
return this
|
|
460
|
+
return this.year;
|
|
467
461
|
case 'month':
|
|
468
|
-
return this
|
|
462
|
+
return this.isoMonth;
|
|
469
463
|
case 'day':
|
|
470
|
-
return this
|
|
464
|
+
return this.date;
|
|
471
465
|
case 'week':
|
|
472
466
|
return this.getWeek();
|
|
473
467
|
case 'hour':
|
|
474
|
-
return this
|
|
468
|
+
return this.hour;
|
|
475
469
|
case 'minute':
|
|
476
|
-
return this
|
|
470
|
+
return this.minute;
|
|
477
471
|
case 'second':
|
|
478
|
-
return this
|
|
472
|
+
return this.second;
|
|
479
473
|
case 'millisecond':
|
|
480
|
-
return this
|
|
474
|
+
return this.millisecond;
|
|
481
475
|
}
|
|
482
476
|
}
|
|
483
477
|
set(unit, value) {
|
|
@@ -511,7 +505,7 @@ export class Chronos {
|
|
|
511
505
|
}
|
|
512
506
|
diff(other, unit) {
|
|
513
507
|
const time = _a.#cast(other);
|
|
514
|
-
const msDiff = this.#
|
|
508
|
+
const msDiff = this.#timestamp - time.#timestamp;
|
|
515
509
|
switch (unit) {
|
|
516
510
|
case 'millisecond':
|
|
517
511
|
return msDiff;
|
|
@@ -537,7 +531,7 @@ export class Chronos {
|
|
|
537
531
|
}
|
|
538
532
|
}
|
|
539
533
|
calendar(baseDate) {
|
|
540
|
-
const base = baseDate ?
|
|
534
|
+
const base = baseDate ? _a.#cast(baseDate) : new _a();
|
|
541
535
|
const input = this.startOf('day');
|
|
542
536
|
const comparison = base.startOf('day');
|
|
543
537
|
const diff = input.diff(comparison, 'day');
|
|
@@ -648,12 +642,12 @@ export class Chronos {
|
|
|
648
642
|
}
|
|
649
643
|
toUTC() {
|
|
650
644
|
const offset = this.getTimeZoneOffsetMinutes();
|
|
651
|
-
const utc = new Date(this.#
|
|
645
|
+
const utc = new Date(this.#timestamp - offset * 60 * 1000);
|
|
652
646
|
return new _a(utc).#withOrigin('toUTC', 'UTC+00:00', 'Greenwich Mean Time', 'UTC');
|
|
653
647
|
}
|
|
654
648
|
toLocal() {
|
|
655
649
|
const offset = this.getTimeZoneOffsetMinutes() - this.getUTCOffsetMinutes();
|
|
656
|
-
const localTime = new Date(this.#
|
|
650
|
+
const localTime = new Date(this.#timestamp - offset * 60 * 1000);
|
|
657
651
|
return new _a(localTime).#withOrigin('toLocal');
|
|
658
652
|
}
|
|
659
653
|
day(index) {
|
|
@@ -668,10 +662,10 @@ export class Chronos {
|
|
|
668
662
|
if (options) {
|
|
669
663
|
if ('from' in options || 'to' in options) {
|
|
670
664
|
if (options?.from) {
|
|
671
|
-
startDate =
|
|
665
|
+
startDate = _a.#cast(options?.from);
|
|
672
666
|
}
|
|
673
667
|
if (options?.to) {
|
|
674
|
-
endDate =
|
|
668
|
+
endDate = _a.#cast(options?.to);
|
|
675
669
|
}
|
|
676
670
|
}
|
|
677
671
|
else if ('span' in options || 'unit' in options) {
|
|
@@ -768,8 +762,7 @@ export class Chronos {
|
|
|
768
762
|
}
|
|
769
763
|
static today(options) {
|
|
770
764
|
const { format = 'dd, mmm DD, YYYY HH:mm:ss', useUTC = false } = options || {};
|
|
771
|
-
|
|
772
|
-
return new _a(today).#format(format, useUTC);
|
|
765
|
+
return new _a().#format(format, useUTC);
|
|
773
766
|
}
|
|
774
767
|
static yesterday() {
|
|
775
768
|
const today = new Date();
|
|
@@ -787,7 +780,7 @@ export class Chronos {
|
|
|
787
780
|
static utc(dateLike) {
|
|
788
781
|
const chronos = new _a(dateLike);
|
|
789
782
|
const offset = chronos.getTimeZoneOffsetMinutes();
|
|
790
|
-
const utc = new Date(chronos.#
|
|
783
|
+
const utc = new Date(chronos.#timestamp - offset * 60 * 1000);
|
|
791
784
|
return new _a(utc).#withOrigin('utc', 'UTC+00:00', 'Greenwich Mean Time', 'UTC');
|
|
792
785
|
}
|
|
793
786
|
static formatTimePart(time, format) {
|
|
@@ -803,10 +796,10 @@ export class Chronos {
|
|
|
803
796
|
if (options) {
|
|
804
797
|
if ('from' in options || 'to' in options) {
|
|
805
798
|
if (options?.from) {
|
|
806
|
-
startDate =
|
|
799
|
+
startDate = _a.#cast(options?.from);
|
|
807
800
|
}
|
|
808
801
|
if (options?.to) {
|
|
809
|
-
endDate =
|
|
802
|
+
endDate = _a.#cast(options?.to);
|
|
810
803
|
}
|
|
811
804
|
}
|
|
812
805
|
else if ('span' in options || 'unit' in options) {
|
|
@@ -831,7 +824,7 @@ export class Chronos {
|
|
|
831
824
|
let winner = _a.#cast(dates[0]);
|
|
832
825
|
for (const d of dates) {
|
|
833
826
|
const c = _a.#cast(d);
|
|
834
|
-
if (c.
|
|
827
|
+
if (c.getTimeStamp() < winner.getTimeStamp()) {
|
|
835
828
|
winner = c;
|
|
836
829
|
}
|
|
837
830
|
}
|
|
@@ -841,7 +834,7 @@ export class Chronos {
|
|
|
841
834
|
let winner = _a.#cast(dates[0]);
|
|
842
835
|
for (const d of dates) {
|
|
843
836
|
const c = _a.#cast(d);
|
|
844
|
-
if (c.
|
|
837
|
+
if (c.getTimeStamp() > winner.getTimeStamp()) {
|
|
845
838
|
winner = c;
|
|
846
839
|
}
|
|
847
840
|
}
|
|
@@ -858,7 +851,7 @@ export class Chronos {
|
|
|
858
851
|
}
|
|
859
852
|
}
|
|
860
853
|
else {
|
|
861
|
-
year =
|
|
854
|
+
year = _a.#cast(date).year;
|
|
862
855
|
}
|
|
863
856
|
return isLeapYear(year);
|
|
864
857
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nhb-toolbox",
|
|
3
|
-
"version": "4.26.
|
|
3
|
+
"version": "4.26.69",
|
|
4
4
|
"description": "A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|