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 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
@@ -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.timestamp];
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.valueOf();
68
+ return this.getTimeStamp();
69
69
  return this.toLocalISOString();
70
70
  }
71
71
  [Symbol.replace](string, replacement) {
72
- return string.replace(this.#removeUTCFromISO(true), replacement);
72
+ return string.replace(this.#removeUTCFromISO(), replacement);
73
73
  }
74
74
  [Symbol.search](string) {
75
- return string.indexOf(this.#removeUTCFromISO(true));
75
+ return string.indexOf(this.#removeUTCFromISO());
76
76
  }
77
77
  [Symbol.split](string) {
78
- return string.split(this.#removeUTCFromISO(true));
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: timeZone,
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 = false) {
210
+ #removeUTCFromISO(local = true) {
211
+ const search = /\.\d+(Z|[+-]\d{2}:\d{2})?$/;
212
212
  return local ?
213
- this.toLocalISOString().replace(/\.\d+(Z|[+-]\d{2}:\d{2})?$/, '')
214
- : this.toISOString().replace(/\.\d+(Z|[+-]\d{2}:\d{2})?$/, '');
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.#date.getTime() - adjustmentMs);
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
- const time = _a.#cast(other);
326
- return this.#timestamp === time.#timestamp;
325
+ return this.#timestamp === _a.#cast(other).#timestamp;
327
326
  }
328
327
  isEqualOrBefore(other) {
329
- const time = _a.#cast(other);
330
- return this.#timestamp <= time.#timestamp;
328
+ return this.#timestamp <= _a.#cast(other).#timestamp;
331
329
  }
332
330
  isEqualOrAfter(other) {
333
- const time = _a.#cast(other);
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
- time.startOf(unit, weekStartsOn).#timestamp);
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
- time.startOf(unit, weekStartsOn).#timestamp);
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
- time.startOf(unit, weekStartsOn).#timestamp);
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 = new _a(start).valueOf();
359
- const e = new _a(end).valueOf();
360
- const t = this.valueOf();
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.#date.getFullYear();
463
+ return this.year;
470
464
  case 'month':
471
- return this.#date.getMonth();
465
+ return this.isoMonth;
472
466
  case 'day':
473
- return this.#date.getDate();
467
+ return this.date;
474
468
  case 'week':
475
469
  return this.getWeek();
476
470
  case 'hour':
477
- return this.#date.getHours();
471
+ return this.hour;
478
472
  case 'minute':
479
- return this.#date.getMinutes();
473
+ return this.minute;
480
474
  case 'second':
481
- return this.#date.getSeconds();
475
+ return this.second;
482
476
  case 'millisecond':
483
- return this.#date.getMilliseconds();
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.#date.getTime() - time.#date.getTime();
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 ? new _a(baseDate) : new _a();
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.#date.getTime() - offset * 60 * 1000);
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.#date.getTime() - offset * 60 * 1000);
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 = new _a(options?.from);
668
+ startDate = _a.#cast(options?.from);
675
669
  }
676
670
  if (options?.to) {
677
- endDate = new _a(options?.to);
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
- const today = new Date();
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.#date.getTime() - offset * 60 * 1000);
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 = new _a(options?.from);
802
+ startDate = _a.#cast(options?.from);
810
803
  }
811
804
  if (options?.to) {
812
- endDate = new _a(options?.to);
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.timestamp < winner.timestamp) {
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.timestamp > winner.timestamp) {
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 = date instanceof _a ? date.year : new _a(date).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: TimeUnit): number;
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`.
@@ -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 valid unit suffix for {@link Date} getter methods (e.g., 'getFullYear', 'getMonth' etc.). */
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 return as local ISO string or UTC ISO string. Defaults to `'local'`. */
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 return as local ISO string or UTC ISO string. Defaults to `'local'`. */
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, FlattenPartial, PartialOrRequired } from '../types/index';
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<T extends GenericObject, B extends PartialOrRequired = 'required'>(object: T, options?: SanitizeOptions<T>, _return?: B): B extends 'partial' ? FlattenPartial<T> : T;
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<T extends GenericObject, B extends PartialOrRequired = 'required'>(array: T[], options?: SanitizeOptions<T>, _return?: B): B extends 'partial' ? FlattenPartial<T>[] : T[];
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?: DotNotationKey<T>[];
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 learn more about these complex types.
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 = DeepPartial<Config>;
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
  *
@@ -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.timestamp];
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.valueOf();
65
+ return this.getTimeStamp();
66
66
  return this.toLocalISOString();
67
67
  }
68
68
  [Symbol.replace](string, replacement) {
69
- return string.replace(this.#removeUTCFromISO(true), replacement);
69
+ return string.replace(this.#removeUTCFromISO(), replacement);
70
70
  }
71
71
  [Symbol.search](string) {
72
- return string.indexOf(this.#removeUTCFromISO(true));
72
+ return string.indexOf(this.#removeUTCFromISO());
73
73
  }
74
74
  [Symbol.split](string) {
75
- return string.split(this.#removeUTCFromISO(true));
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: timeZone,
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 = false) {
207
+ #removeUTCFromISO(local = true) {
208
+ const search = /\.\d+(Z|[+-]\d{2}:\d{2})?$/;
209
209
  return local ?
210
- this.toLocalISOString().replace(/\.\d+(Z|[+-]\d{2}:\d{2})?$/, '')
211
- : this.toISOString().replace(/\.\d+(Z|[+-]\d{2}:\d{2})?$/, '');
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.#date.getTime() - adjustmentMs);
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
- const time = _a.#cast(other);
323
- return this.#timestamp === time.#timestamp;
322
+ return this.#timestamp === _a.#cast(other).#timestamp;
324
323
  }
325
324
  isEqualOrBefore(other) {
326
- const time = _a.#cast(other);
327
- return this.#timestamp <= time.#timestamp;
325
+ return this.#timestamp <= _a.#cast(other).#timestamp;
328
326
  }
329
327
  isEqualOrAfter(other) {
330
- const time = _a.#cast(other);
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
- time.startOf(unit, weekStartsOn).#timestamp);
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
- time.startOf(unit, weekStartsOn).#timestamp);
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
- time.startOf(unit, weekStartsOn).#timestamp);
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 = new _a(start).valueOf();
356
- const e = new _a(end).valueOf();
357
- const t = this.valueOf();
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.#date.getFullYear();
460
+ return this.year;
467
461
  case 'month':
468
- return this.#date.getMonth();
462
+ return this.isoMonth;
469
463
  case 'day':
470
- return this.#date.getDate();
464
+ return this.date;
471
465
  case 'week':
472
466
  return this.getWeek();
473
467
  case 'hour':
474
- return this.#date.getHours();
468
+ return this.hour;
475
469
  case 'minute':
476
- return this.#date.getMinutes();
470
+ return this.minute;
477
471
  case 'second':
478
- return this.#date.getSeconds();
472
+ return this.second;
479
473
  case 'millisecond':
480
- return this.#date.getMilliseconds();
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.#date.getTime() - time.#date.getTime();
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 ? new _a(baseDate) : new _a();
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.#date.getTime() - offset * 60 * 1000);
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.#date.getTime() - offset * 60 * 1000);
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 = new _a(options?.from);
665
+ startDate = _a.#cast(options?.from);
672
666
  }
673
667
  if (options?.to) {
674
- endDate = new _a(options?.to);
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
- const today = new Date();
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.#date.getTime() - offset * 60 * 1000);
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 = new _a(options?.from);
799
+ startDate = _a.#cast(options?.from);
807
800
  }
808
801
  if (options?.to) {
809
- endDate = new _a(options?.to);
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.timestamp < winner.timestamp) {
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.timestamp > winner.timestamp) {
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 = date instanceof _a ? date.year : new _a(date).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.64",
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",