@zelgadis87/utils-core 5.5.0-beta.2 → 5.5.0-beta.4

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.
@@ -102,7 +102,9 @@ declare class Optional<T> implements TOptional<T> {
102
102
  private _value;
103
103
  private constructor();
104
104
  getRawValue(): T | undefined;
105
+ /** @deprecated[2026.04.07]: Replace with {@link getOrElseThrow} (drop-in replacement with no arguments) */
105
106
  get(): T;
107
+ getOrElseThrow(): T;
106
108
  getOrElseThrow(errorProducer: TProducer<Error>): T;
107
109
  set(t: T): void;
108
110
  protected setNullable(t: T | null | undefined): void | this;
@@ -141,6 +143,7 @@ declare class Optional<T> implements TOptional<T> {
141
143
 
142
144
  type TOptional<T> = {
143
145
  /**
146
+ * @deprecated[2026.04.07]: Replace with {@link getOrElseThrow} (drop-in replacement with no arguments)
144
147
  * @returns the currently stored value, if any; throws {@link ErrorGetEmptyOptional} otherwise;
145
148
  */
146
149
  get(): T;
@@ -149,9 +152,10 @@ type TOptional<T> = {
149
152
  */
150
153
  getRawValue(): T | undefined;
151
154
  /**
152
- * @returns the currently stored value, if any; throws the error generated by errorProducer otherwise;
155
+ * @returns the currently stored value, if any; throws {@link ErrorGetEmptyOptional} if no errorProducer is provided, or the error generated by errorProducer otherwise;
153
156
  */
154
- getOrElseThrow: (errorProducer: TProducer<Error>) => T;
157
+ getOrElseThrow(): T;
158
+ getOrElseThrow(errorProducer: TProducer<Error>): T;
155
159
  /**
156
160
  * Places a new value inside this optional. Throws {@link ErrorSetEmptyOptional} if t is null or undefined.
157
161
  */
@@ -188,7 +192,10 @@ type TOptional<T> = {
188
192
  filter(predicate: TPredicate<T>): TOptional<T>;
189
193
  };
190
194
  type TEmptyOptional<T> = TOptional<T> & {
195
+ /** @deprecated[2026.04.07]: Replace with {@link getOrElseThrow} (drop-in replacement with no arguments) */
191
196
  get(): never;
197
+ getOrElseThrow(): never;
198
+ getOrElseThrow(errorProducer: TProducer<Error>): never;
192
199
  isEmpty(): true;
193
200
  isPresent(): false;
194
201
  apply<RP = void, RE = void>(callbackIfPresent: TFunction<T, RP>, callbackIfEmpty: TProducer<RE>): RE;
@@ -207,7 +214,10 @@ type TEmptyOptional<T> = TOptional<T> & {
207
214
  orElseProduceNullableAndApply: <R>(newValueProducer: TProducer<R | null | undefined>) => TOptional<R>;
208
215
  };
209
216
  type TPresentOptional<T> = TOptional<T> & {
217
+ /** @deprecated[2026.04.07]: Replace with {@link getOrElseThrow} (drop-in replacement with no arguments) */
210
218
  get(): T;
219
+ getOrElseThrow(): T;
220
+ getOrElseThrow(errorProducer: TProducer<Error>): T;
211
221
  isEmpty(): false;
212
222
  isPresent(): true;
213
223
  apply<RP = void, RE = void>(callbackIfPresent: TFunction<T, RP>, callbackIfEmpty: TProducer<RE>): RP;
@@ -1408,6 +1418,7 @@ declare class Lazy<T> {
1408
1418
  ifPresent(fn: (t: T) => void): void;
1409
1419
  ifEmpty(fn: () => void): void;
1410
1420
  apply(fnPresent: (t: T) => void, fnEmpty: () => void): void;
1421
+ mapOrElse<R>(onPresent: (t: T) => R, onEmpty: () => R): R;
1411
1422
  protected empty(): void;
1412
1423
  static of<T>(generator: () => T): Lazy<T>;
1413
1424
  }
@@ -1676,6 +1687,13 @@ type TAddTransition<T extends readonly TTransitionRecord[], From extends number,
1676
1687
  * - Duplicate transition definitions
1677
1688
  * - Backward transitions (e.g., version 2 → 1)
1678
1689
  *
1690
+ * ## Architectural Convention
1691
+ *
1692
+ * The built DataUpgrader is the **single point of versioning** for your data. Never bypass it
1693
+ * with manual `$version` checks — `upgrade()` is idempotent (no-op on latest version) and
1694
+ * accepts the full `Vstar` union, returning the current latest version. See {@link DataUpgrader}
1695
+ * for the full type aliasing conventions (`Vstar` union, no-suffix alias, adding new versions).
1696
+ *
1679
1697
  * @example
1680
1698
  * ```typescript
1681
1699
  * // Step 1: Define all historical versions with $version discriminator
@@ -1778,6 +1796,49 @@ interface IDataUpgrader<XStar extends TUpgradable, XLatest extends XStar> {
1778
1796
  * finding the shortest upgrade path and applying transformations. This is particularly useful for
1779
1797
  * handling persisted data that may be in any historical format.
1780
1798
  *
1799
+ * ## Architectural Conventions
1800
+ *
1801
+ * ### Type Aliasing
1802
+ * ```typescript
1803
+ * // Xstar = union of ALL known versions (upgrader input type)
1804
+ * type TMyData_Vstar = TMyData_V1 | TMyData_V2 | TMyData_V3;
1805
+ *
1806
+ * // No suffix = alias for the CURRENT latest version (upgrader output type)
1807
+ * type TMyData = TMyData_V3;
1808
+ * // When adding V4 later, update Vstar and change the alias:
1809
+ * // type TMyData_Vstar = TMyData_V1 | TMyData_V2 | TMyData_V3 | TMyData_V4;
1810
+ * // type TMyData = TMyData_V4;
1811
+ * ```
1812
+ *
1813
+ * ### Always Run the Upgrader
1814
+ *
1815
+ * **Every piece of serialized data must be treated as potentially any old version.**
1816
+ *
1817
+ * Never inspect `$version` manually and skip the upgrader. Always feed raw parsed data
1818
+ * directly into `upgrade()`. The upgrader is **idempotent** — calling it on data already
1819
+ * at the latest version is a no-op that returns immediately. Bypassing it creates fragile
1820
+ * fast paths that break when new versions are introduced.
1821
+ *
1822
+ * ```typescript
1823
+ * // ✅ CORRECT — always delegate to the upgrader
1824
+ * const raw = JSON.parse(json) as TMyData_Vstar;
1825
+ * const current = await upgrader.upgrade(raw);
1826
+ *
1827
+ * // ❌ WRONG — manual version check bypasses the upgrader
1828
+ * const raw = JSON.parse(json);
1829
+ * if (raw.$version === 3) {
1830
+ * // This works today, breaks silently when V4 is added
1831
+ * }
1832
+ * ```
1833
+ *
1834
+ * ### Adding a New Version
1835
+ *
1836
+ * 1. Define the new version type with `$version: N`
1837
+ * 2. Add it to the `Vstar` union
1838
+ * 3. Change the no-suffix alias to point to the new version
1839
+ * 4. Add a transition from the previous latest to the new version
1840
+ * 5. Existing code that calls `upgrade()` requires zero changes
1841
+ *
1781
1842
  * **Key Use Case:** Reading serialized data of unknown version and migrating it transparently.
1782
1843
  *
1783
1844
  * @example
@@ -1787,9 +1848,9 @@ interface IDataUpgrader<XStar extends TUpgradable, XLatest extends XStar> {
1787
1848
  * type TSerializedData_V2 = { name: string; age: number; $version: 2 };
1788
1849
  * type TSerializedData_V3 = { name: string; age: number; email: string; $version: 3 };
1789
1850
  *
1790
- * // Step 2: Create union type and current version type
1851
+ * // Step 2: Create Vstar union (all versions) and current-version alias (latest only)
1791
1852
  * type TSerializedData_Vstar = TSerializedData_V1 | TSerializedData_V2 | TSerializedData_V3;
1792
- * type TSerializedData = TSerializedData_V3;
1853
+ * type TSerializedData = TSerializedData_V3; // Update this when adding V4
1793
1854
  *
1794
1855
  * // Step 3: Create upgrader with transition functions
1795
1856
  * const upgrader = DataUpgrader.create<TSerializedData_Vstar, TSerializedData>(3)
package/.rollup/index.mjs CHANGED
@@ -222,10 +222,11 @@ class Optional {
222
222
  getRawValue() {
223
223
  return this._value;
224
224
  }
225
+ /** @deprecated[2026.04.07]: Replace with {@link getOrElseThrow} (drop-in replacement with no arguments) */
225
226
  get() {
226
- return this.getOrElseThrow(() => new ErrorGetEmptyOptional());
227
+ return this.getOrElseThrow();
227
228
  }
228
- getOrElseThrow(errorProducer) {
229
+ getOrElseThrow(errorProducer = () => new ErrorGetEmptyOptional()) {
229
230
  if (this.isEmpty())
230
231
  throw errorProducer();
231
232
  return this._value;
@@ -1585,6 +1586,9 @@ class Lazy {
1585
1586
  fnEmpty();
1586
1587
  }
1587
1588
  }
1589
+ mapOrElse(onPresent, onEmpty) {
1590
+ return this._initialized ? onPresent(this._value) : onEmpty();
1591
+ }
1588
1592
  empty() {
1589
1593
  this._initialized = false;
1590
1594
  }
@@ -3797,6 +3801,49 @@ const VERSION_FIELD = "$version";
3797
3801
  * finding the shortest upgrade path and applying transformations. This is particularly useful for
3798
3802
  * handling persisted data that may be in any historical format.
3799
3803
  *
3804
+ * ## Architectural Conventions
3805
+ *
3806
+ * ### Type Aliasing
3807
+ * ```typescript
3808
+ * // Xstar = union of ALL known versions (upgrader input type)
3809
+ * type TMyData_Vstar = TMyData_V1 | TMyData_V2 | TMyData_V3;
3810
+ *
3811
+ * // No suffix = alias for the CURRENT latest version (upgrader output type)
3812
+ * type TMyData = TMyData_V3;
3813
+ * // When adding V4 later, update Vstar and change the alias:
3814
+ * // type TMyData_Vstar = TMyData_V1 | TMyData_V2 | TMyData_V3 | TMyData_V4;
3815
+ * // type TMyData = TMyData_V4;
3816
+ * ```
3817
+ *
3818
+ * ### Always Run the Upgrader
3819
+ *
3820
+ * **Every piece of serialized data must be treated as potentially any old version.**
3821
+ *
3822
+ * Never inspect `$version` manually and skip the upgrader. Always feed raw parsed data
3823
+ * directly into `upgrade()`. The upgrader is **idempotent** — calling it on data already
3824
+ * at the latest version is a no-op that returns immediately. Bypassing it creates fragile
3825
+ * fast paths that break when new versions are introduced.
3826
+ *
3827
+ * ```typescript
3828
+ * // ✅ CORRECT — always delegate to the upgrader
3829
+ * const raw = JSON.parse(json) as TMyData_Vstar;
3830
+ * const current = await upgrader.upgrade(raw);
3831
+ *
3832
+ * // ❌ WRONG — manual version check bypasses the upgrader
3833
+ * const raw = JSON.parse(json);
3834
+ * if (raw.$version === 3) {
3835
+ * // This works today, breaks silently when V4 is added
3836
+ * }
3837
+ * ```
3838
+ *
3839
+ * ### Adding a New Version
3840
+ *
3841
+ * 1. Define the new version type with `$version: N`
3842
+ * 2. Add it to the `Vstar` union
3843
+ * 3. Change the no-suffix alias to point to the new version
3844
+ * 4. Add a transition from the previous latest to the new version
3845
+ * 5. Existing code that calls `upgrade()` requires zero changes
3846
+ *
3800
3847
  * **Key Use Case:** Reading serialized data of unknown version and migrating it transparently.
3801
3848
  *
3802
3849
  * @example
@@ -3806,9 +3853,9 @@ const VERSION_FIELD = "$version";
3806
3853
  * type TSerializedData_V2 = { name: string; age: number; $version: 2 };
3807
3854
  * type TSerializedData_V3 = { name: string; age: number; email: string; $version: 3 };
3808
3855
  *
3809
- * // Step 2: Create union type and current version type
3856
+ * // Step 2: Create Vstar union (all versions) and current-version alias (latest only)
3810
3857
  * type TSerializedData_Vstar = TSerializedData_V1 | TSerializedData_V2 | TSerializedData_V3;
3811
- * type TSerializedData = TSerializedData_V3;
3858
+ * type TSerializedData = TSerializedData_V3; // Update this when adding V4
3812
3859
  *
3813
3860
  * // Step 3: Create upgrader with transition functions
3814
3861
  * const upgrader = DataUpgrader.create<TSerializedData_Vstar, TSerializedData>(3)
@@ -3948,6 +3995,13 @@ function isUpgradable(obj) {
3948
3995
  * - Duplicate transition definitions
3949
3996
  * - Backward transitions (e.g., version 2 → 1)
3950
3997
  *
3998
+ * ## Architectural Convention
3999
+ *
4000
+ * The built DataUpgrader is the **single point of versioning** for your data. Never bypass it
4001
+ * with manual `$version` checks — `upgrade()` is idempotent (no-op on latest version) and
4002
+ * accepts the full `Vstar` union, returning the current latest version. See {@link DataUpgrader}
4003
+ * for the full type aliasing conventions (`Vstar` union, no-suffix alias, adding new versions).
4004
+ *
3951
4005
  * @example
3952
4006
  * ```typescript
3953
4007
  * // Step 1: Define all historical versions with $version discriminator