@zelgadis87/utils-core 5.4.4 → 5.4.6
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/.rollup/index.cjs +234 -2
- package/.rollup/index.cjs.map +1 -1
- package/.rollup/index.d.ts +188 -3
- package/.rollup/index.mjs +234 -3
- package/.rollup/index.mjs.map +1 -1
- package/.rollup/tsconfig.tsbuildinfo +1 -1
- package/CHANGELOG.md +13 -0
- package/package.json +2 -1
- package/src/upgrade/DataUpgrader.ts +109 -4
- package/src/upgrade/DataUpgraderBuilder.ts +168 -0
- package/src/upgrade/_index.ts +1 -0
- package/src/utils/css.ts +1 -1
- package/src/utils/operations.ts +27 -1
package/.rollup/index.d.ts
CHANGED
|
@@ -1020,7 +1020,7 @@ type TCssSelectorDeclarationRulesDictionary = {
|
|
|
1020
1020
|
[selector: string]: TCssDeclarationRulesDictionary | TCssSelectorDeclarationRulesDictionary;
|
|
1021
1021
|
};
|
|
1022
1022
|
declare function cssDeclarationRulesDictionaryToCss(syleDeclarationRulesForSelectorsProduceable: TProduceable<TCssSelectorDeclarationRulesDictionary>, indent?: number): string;
|
|
1023
|
-
declare function transformCssDictionary(dict: TCssSelectorDeclarationRulesDictionary, transformer: (key: TCssGenericDeclarationKey, value: string) => string): TCssSelectorDeclarationRulesDictionary;
|
|
1023
|
+
declare function transformCssDictionary(dict: TCssDeclarationRulesDictionary | TCssSelectorDeclarationRulesDictionary, transformer: (key: TCssGenericDeclarationKey, value: string) => string): TCssSelectorDeclarationRulesDictionary;
|
|
1024
1024
|
type TProduceable<T> = T | TProducer<T>;
|
|
1025
1025
|
|
|
1026
1026
|
/**
|
|
@@ -1108,7 +1108,7 @@ type TOperationAggregateFlattenedError<E> = E extends OperationAggregateError<in
|
|
|
1108
1108
|
* @param results - Array of operation results to combine
|
|
1109
1109
|
* @returns A single operation with either all data or all aggregated errors (flattened)
|
|
1110
1110
|
*/
|
|
1111
|
-
declare function combine<T, E = Error>(results: TReadableArray<TOperation<T, E
|
|
1111
|
+
declare function combine<T, E = Error>(results: TReadableArray<TOperation<T, E | OperationAggregateError<E>>>): TOperation<T[], OperationAggregateError<TOperationAggregateFlattenedError<E>>>;
|
|
1112
1112
|
declare const Operation: {
|
|
1113
1113
|
ok: <const T>(data: T) => {
|
|
1114
1114
|
readonly success: true;
|
|
@@ -1145,6 +1145,26 @@ declare const Operation: {
|
|
|
1145
1145
|
* @returns A tuple of [successes, failures]
|
|
1146
1146
|
*/
|
|
1147
1147
|
partition: <T, E = Error>(results: TReadableArray<TOperation<T, E>>) => [TOperationSuccess<T>[], TOperationFailure<E>[]];
|
|
1148
|
+
/**
|
|
1149
|
+
* Transforms the success value of an operation using the provided function.
|
|
1150
|
+
* If the operation is a failure, it is returned unchanged (same reference).
|
|
1151
|
+
* The transformation function is never called on a failure.
|
|
1152
|
+
*
|
|
1153
|
+
* @template T - The input success data type
|
|
1154
|
+
* @template U - The output success data type
|
|
1155
|
+
* @template E - The error type (preserved exactly)
|
|
1156
|
+
* @param op - The operation result to transform
|
|
1157
|
+
* @param fn - Pure function applied to the success value
|
|
1158
|
+
* @returns A new success with the transformed value, or the original failure
|
|
1159
|
+
*
|
|
1160
|
+
* @example
|
|
1161
|
+
* Operation.map(Operation.ok(1), x => x * 2);
|
|
1162
|
+
* // => { success: true, data: 2 }
|
|
1163
|
+
*
|
|
1164
|
+
* Operation.map(Operation.ko('err'), x => x * 2);
|
|
1165
|
+
* // => { success: false, error: 'err' }
|
|
1166
|
+
*/
|
|
1167
|
+
map: <T, U, E>(op: TOperation<T, E>, fn: (data: T) => U) => TOperation<U, E>;
|
|
1148
1168
|
combine: typeof combine;
|
|
1149
1169
|
};
|
|
1150
1170
|
|
|
@@ -1583,10 +1603,170 @@ type TPossibleVersion<XStar extends TUpgradable> = XStar["$version"] & number;
|
|
|
1583
1603
|
type TPossibleFromVersion<XStar extends TUpgradable, XLatest extends XStar> = Exclude<TPossibleVersion<XStar>, XLatest["$version"]>;
|
|
1584
1604
|
type TUpgradeFunction<XStar extends TUpgradable, XFrom extends XStar, XTo extends XStar> = TFunction<Readonly<TVersionMap<XStar>[XFrom["$version"]]>, TPromisable<TVersionMap<XStar>[XTo["$version"]]>>;
|
|
1585
1605
|
|
|
1606
|
+
type TTransitionRecord = readonly [from: number, to: number];
|
|
1607
|
+
type TContainsTransition<T extends readonly TTransitionRecord[], From extends number, To extends number> = T extends readonly [infer First, ...infer Rest] ? First extends readonly [From, To] ? true : TContainsTransition<Rest & readonly TTransitionRecord[], From, To> : false;
|
|
1608
|
+
type TAddTransition<T extends readonly TTransitionRecord[], From extends number, To extends number> = TContainsTransition<T, From, To> extends true ? never : readonly [...T, readonly [From, To]];
|
|
1609
|
+
/**
|
|
1610
|
+
* Builder for creating type-safe DataUpgrader instances with compile-time safety.
|
|
1611
|
+
*
|
|
1612
|
+
* Prevents at compile-time:
|
|
1613
|
+
* - Missing upgrade paths (incomplete version coverage)
|
|
1614
|
+
* - Duplicate transition definitions
|
|
1615
|
+
* - Backward transitions (e.g., version 2 → 1)
|
|
1616
|
+
*
|
|
1617
|
+
* @example
|
|
1618
|
+
* ```typescript
|
|
1619
|
+
* // Step 1: Define all historical versions with $version discriminator
|
|
1620
|
+
* type V1 = { name: string; $version: 1 };
|
|
1621
|
+
* type V2 = { name: string; age: number; $version: 2 };
|
|
1622
|
+
* type V3 = { name: string; age: number; email: string; $version: 3 };
|
|
1623
|
+
*
|
|
1624
|
+
* // Step 2: Build the upgrader with type-safe transitions
|
|
1625
|
+
* const upgrader = DataUpgraderBuilder.start<V1>()
|
|
1626
|
+
* .addTransition<V2>(2, async (data) => ({
|
|
1627
|
+
* ...data,
|
|
1628
|
+
* age: 0,
|
|
1629
|
+
* $version: 2
|
|
1630
|
+
* }))
|
|
1631
|
+
* .addTransition<V3>(3, async (data) => ({
|
|
1632
|
+
* ...data,
|
|
1633
|
+
* email: "",
|
|
1634
|
+
* $version: 3
|
|
1635
|
+
* }))
|
|
1636
|
+
* .addShortcut<V1, V3>(1, 3, async (data) => ({
|
|
1637
|
+
* // Optional: Direct path for efficiency
|
|
1638
|
+
* ...data,
|
|
1639
|
+
* age: 0,
|
|
1640
|
+
* email: "",
|
|
1641
|
+
* $version: 3
|
|
1642
|
+
* }))
|
|
1643
|
+
* .build(3);
|
|
1644
|
+
*
|
|
1645
|
+
* // Step 3: Use the upgrader
|
|
1646
|
+
* async function loadData(json: string): Promise<V3> {
|
|
1647
|
+
* const data = JSON.parse(json);
|
|
1648
|
+
* return await upgrader.upgrade(data);
|
|
1649
|
+
* }
|
|
1650
|
+
*
|
|
1651
|
+
* // Works with any version:
|
|
1652
|
+
* const v1 = await loadData('{"name":"Alice","$version":1}'); // → V3
|
|
1653
|
+
* const v2 = await loadData('{"name":"Bob","age":25,"$version":2}'); // → V3
|
|
1654
|
+
* const v3 = await loadData('{"name":"Carol","age":30,"email":"c@example.com","$version":3}'); // → V3
|
|
1655
|
+
* ```
|
|
1656
|
+
*/
|
|
1657
|
+
declare class DataUpgraderBuilder<VLowest extends TUpgradable, VUnion extends TUpgradable = VLowest, VLatest extends TUpgradable = VLowest, TTransitions extends readonly TTransitionRecord[] = readonly []> {
|
|
1658
|
+
private latestVersion;
|
|
1659
|
+
private transitions;
|
|
1660
|
+
private constructor();
|
|
1661
|
+
/** Starts building a new DataUpgrader from the lowest version. */
|
|
1662
|
+
static start<V1 extends TUpgradable>(): DataUpgraderBuilder<V1, V1, V1, readonly []>;
|
|
1663
|
+
/**
|
|
1664
|
+
* Adds a sequential transition from the current latest version to a new version.
|
|
1665
|
+
* Only the new version type needs to be specified.
|
|
1666
|
+
*
|
|
1667
|
+
* @example
|
|
1668
|
+
* ```typescript
|
|
1669
|
+
* builder.addTransition<V2>(2, async (d) => ({ ...d, extra: 0, $version: 2 }))
|
|
1670
|
+
* ```
|
|
1671
|
+
*/
|
|
1672
|
+
addTransition<VNext extends TUpgradable, NewUnion extends TUpgradable = VUnion | VNext, LatestNumber extends number = VLatest["$version"], NextNumber extends number = VNext["$version"], NewTransitions extends readonly TTransitionRecord[] = TAddTransition<TTransitions, LatestNumber, NextNumber>>(toVersion: NextNumber, apply: (data: VLatest) => Promise<VNext> | VNext): DataUpgraderBuilder<VLowest, NewUnion, VNext, NewTransitions>;
|
|
1673
|
+
/**
|
|
1674
|
+
* Adds a shortcut transition between arbitrary versions.
|
|
1675
|
+
* Both versions must already be in the accumulated union type.
|
|
1676
|
+
*
|
|
1677
|
+
* @example
|
|
1678
|
+
* ```typescript
|
|
1679
|
+
* builder.addShortcut<V1, V3>(1, 3, async (d) => ({ ...d, extra: 0, flag: false, $version: 3 }))
|
|
1680
|
+
* ```
|
|
1681
|
+
*/
|
|
1682
|
+
addShortcut<VFrom extends TUpgradable & VUnion, VTo extends TUpgradable & VUnion, From extends number = VFrom["$version"], To extends number = VTo["$version"], NewTransitions extends readonly TTransitionRecord[] = TAddTransition<TTransitions, From, To>>(fromVersion: From, toVersion: To, apply: (data: VFrom) => Promise<VTo> | VTo): DataUpgraderBuilder<VLowest, VUnion, VLatest, NewTransitions>;
|
|
1683
|
+
/**
|
|
1684
|
+
* Builds the DataUpgrader with the current latest version.
|
|
1685
|
+
*
|
|
1686
|
+
* @example
|
|
1687
|
+
* ```typescript
|
|
1688
|
+
* const upgrader = builder.build(3);
|
|
1689
|
+
* ```
|
|
1690
|
+
*/
|
|
1691
|
+
build(latestVersion: VLatest["$version"]): DataUpgrader<VUnion, Extract<VUnion, {
|
|
1692
|
+
$version: VLatest["$version"];
|
|
1693
|
+
}>>;
|
|
1694
|
+
/** @internal */
|
|
1695
|
+
getTransitions(): Record<number, Record<number, {
|
|
1696
|
+
from: number;
|
|
1697
|
+
to: number;
|
|
1698
|
+
apply: (data: unknown) => Promise<unknown>;
|
|
1699
|
+
}>>;
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1586
1702
|
declare const VERSION_FIELD = "$version";
|
|
1587
1703
|
interface IDataUpgrader<XStar extends TUpgradable, XLatest extends XStar> {
|
|
1704
|
+
/**
|
|
1705
|
+
* Upgrades data from any version to the latest version.
|
|
1706
|
+
*
|
|
1707
|
+
* @param data - Data object from any version (must contain valid $version field)
|
|
1708
|
+
* @returns Promise resolving to data at the latest version
|
|
1709
|
+
*/
|
|
1588
1710
|
upgrade(data: XStar): Promise<XLatest>;
|
|
1589
1711
|
}
|
|
1712
|
+
/**
|
|
1713
|
+
* Versioned data migration system for transparently upgrading serialized data to the latest version.
|
|
1714
|
+
*
|
|
1715
|
+
* DataUpgrader manages the migration of data structures across multiple versions, automatically
|
|
1716
|
+
* finding the shortest upgrade path and applying transformations. This is particularly useful for
|
|
1717
|
+
* handling persisted data that may be in any historical format.
|
|
1718
|
+
*
|
|
1719
|
+
* **Key Use Case:** Reading serialized data of unknown version and migrating it transparently.
|
|
1720
|
+
*
|
|
1721
|
+
* @example
|
|
1722
|
+
* ```typescript
|
|
1723
|
+
* // Step 1: Define all historical versions with $version discriminator
|
|
1724
|
+
* type TSerializedData_V1 = { name: string; $version: 1 };
|
|
1725
|
+
* type TSerializedData_V2 = { name: string; age: number; $version: 2 };
|
|
1726
|
+
* type TSerializedData_V3 = { name: string; age: number; email: string; $version: 3 };
|
|
1727
|
+
*
|
|
1728
|
+
* // Step 2: Create union type and current version type
|
|
1729
|
+
* type TSerializedData_Vstar = TSerializedData_V1 | TSerializedData_V2 | TSerializedData_V3;
|
|
1730
|
+
* type TSerializedData = TSerializedData_V3;
|
|
1731
|
+
*
|
|
1732
|
+
* // Step 3: Create upgrader with transition functions
|
|
1733
|
+
* const upgrader = DataUpgrader.create<TSerializedData_Vstar, TSerializedData>(3)
|
|
1734
|
+
* .addTransition(1, 2, async (data: TSerializedData_V1) => ({
|
|
1735
|
+
* ...data,
|
|
1736
|
+
* age: 0,
|
|
1737
|
+
* $version: 2
|
|
1738
|
+
* }))
|
|
1739
|
+
* .addTransition(2, 3, async (data: TSerializedData_V2) => ({
|
|
1740
|
+
* ...data,
|
|
1741
|
+
* email: "",
|
|
1742
|
+
* $version: 3
|
|
1743
|
+
* }))
|
|
1744
|
+
* .addTransition(1, 3, async (data: TSerializedData_V1) => ({
|
|
1745
|
+
* // Optional: Direct path for efficiency
|
|
1746
|
+
* ...data,
|
|
1747
|
+
* age: 0,
|
|
1748
|
+
* email: "",
|
|
1749
|
+
* $version: 3
|
|
1750
|
+
* }));
|
|
1751
|
+
*
|
|
1752
|
+
* // Step 4: Use in data loading - handles any version transparently
|
|
1753
|
+
* async function loadData(json: string): Promise<TSerializedData> {
|
|
1754
|
+
* const data = parseJson<TSerializedData_Vstar>(json);
|
|
1755
|
+
* return await upgrader.upgrade(data);
|
|
1756
|
+
* }
|
|
1757
|
+
*
|
|
1758
|
+
* // Works with any version:
|
|
1759
|
+
* const v1 = await loadData('{"name":"Alice","$version":1}'); // → V3
|
|
1760
|
+
* const v2 = await loadData('{"name":"Bob","age":25,"$version":2}'); // → V3
|
|
1761
|
+
* const v3 = await loadData('{"name":"Carol","age":30,"email":"c@example.com","$version":3}'); // → V3
|
|
1762
|
+
* ```
|
|
1763
|
+
*
|
|
1764
|
+
* @typeParam X - Union type of all possible data versions (must extend TUpgradable)
|
|
1765
|
+
* @typeParam XLatest - The latest version type (must extend X)
|
|
1766
|
+
*
|
|
1767
|
+
* @see {@link isUpgradable | Type guard for checking if data is upgradable}
|
|
1768
|
+
* @see {@link DataUpgrader.Errors | Error types for upgrade failures}
|
|
1769
|
+
*/
|
|
1590
1770
|
declare class DataUpgrader<X extends TUpgradable, XLatest extends X> implements IDataUpgrader<X, XLatest> {
|
|
1591
1771
|
private latestVersion;
|
|
1592
1772
|
private transitions;
|
|
@@ -1595,6 +1775,11 @@ declare class DataUpgrader<X extends TUpgradable, XLatest extends X> implements
|
|
|
1595
1775
|
upgrade(data: X): Promise<XLatest>;
|
|
1596
1776
|
isLatestVersion(data: X): data is XLatest;
|
|
1597
1777
|
static create<X extends TUpgradable, XLatestVersion extends X>(latest: XLatestVersion[typeof VERSION_FIELD]): DataUpgrader<X, XLatestVersion>;
|
|
1778
|
+
/**
|
|
1779
|
+
* Creates a DataUpgrader from a DataUpgraderBuilder instance.
|
|
1780
|
+
* @internal
|
|
1781
|
+
*/
|
|
1782
|
+
static fromBuilder<X extends TUpgradable, XLatestVersion extends X>(builder: DataUpgraderBuilder<any, X, any>, latestVersion: XLatestVersion[typeof VERSION_FIELD]): DataUpgrader<X, XLatestVersion>;
|
|
1598
1783
|
static Errors: {
|
|
1599
1784
|
readonly EmptyUpgrade: typeof EmptyUpgradeError;
|
|
1600
1785
|
readonly UnavailableUpgrade: typeof UnavailableUpgradeError;
|
|
@@ -1602,5 +1787,5 @@ declare class DataUpgrader<X extends TUpgradable, XLatest extends X> implements
|
|
|
1602
1787
|
}
|
|
1603
1788
|
declare function isUpgradable(obj: TJsonSerializable): obj is TUpgradable;
|
|
1604
1789
|
|
|
1605
|
-
export { Cached, DataUpgrader, Deferred, DeferredCanceledError, ErrorCannotInstantiatePresentOptionalWithEmptyValue, ErrorGetEmptyOptional, ErrorSetEmptyOptional, Lazy, LazyAsync, LazyDictionary, Logger, NEVER, NonExhaustiveSwitchError, Operation, OperationAggregateError, Optional, PredicateBuilder, RandomTimeDuration, RateThrottler, Semaphore, Sorter, StringParts, TimeDuration, TimeFrequency, TimeInstant, TimeRange, TimeUnit, TimeoutError, alwaysFalse, alwaysTrue, and, arrayGet, arrayIncludes, asError, asPromise, average, averageBy, awaitAtMost, capitalizeWord, clamp, clampInt0_100, constant, constantFalse, constantNull, constantOne, constantTrue, constantUndefined, constantZero, cssDeclarationRulesDictionaryToCss, decrement, decrementBy, delayPromise, dictToEntries, dictToList, divideBy, ellipsis, ensureArray, ensureDefined, ensureNegativeNumber, ensureNonNegativeNumber, ensureNonPositiveNumber, ensurePositiveNumber, ensureReadableArray, entriesToDict, entriesToEntries, entriesToList, extendArray, extendArrayWith, fill, fillWith, filterMap, filterMapReduce, filterWithTypePredicate, findInArray, findIndexInArray, first, flatMapTruthys, getCauseMessageFromError, getCauseStackFromError, getMessageFromError, getStackFromError, groupByBoolean, groupByBooleanWith, groupByNumber, groupByNumberWith, groupByString, groupByStringWith, groupBySymbol, groupBySymbolWith, hashCode, havingMaxBy, havingMinBy, head, identity, ifDefined, ifNullOrUndefined, iff, includes, increment, incrementBy, indexByNumber, indexByNumberWith, indexByString, indexByStringWith, indexBySymbol, indexBySymbolWith, indexByWith, isAllowedTimeDuration, isArray, isDefined, isEmpty, isError, isFalse, isFunction, isNegativeNumber, isNullOrUndefined, isNullOrUndefinedOrEmpty, isNumber, isPositiveNumber, isString, isTimeInstant, isTrue, isUpgradable, isZero, jsonCloneDeep, last, listToDict, mapDefined, mapEntries, mapFirstTruthy, mapTruthys, max, maxBy, min, minBy, multiplyBy, noop, not, omitFromJsonObject, or, pad, padLeft, padRight, parseJson, parseTimeInstantBasicComponents, parseTimeInstantComponents, partition, pick, pipedInvoke, pipedInvokeFromArray, pluralize, promiseSequence, randomDecimalInInterval, randomId, randomIntegerInInterval, randomNumberInInterval, randomPick, randomPicks, range, repeat, reverse, round, roundAwayFromZero, roundToLower, roundToNearest, roundToUpper, roundTowardsZero, shallowArrayEquals, shallowRecordEquals, sortedArray, splitWords, stringToNumber, stringifyJson, sum, sumBy, tail, throttle, throwIfNullOrUndefined, transformCssDictionary, tryToParseJson, tryToParseNumber, uniq, uniqBy, uniqByKey, unzip, upsert, withTryCatch, withTryCatchAsync, wrapWithString, xor, zip };
|
|
1790
|
+
export { Cached, DataUpgrader, DataUpgraderBuilder, Deferred, DeferredCanceledError, ErrorCannotInstantiatePresentOptionalWithEmptyValue, ErrorGetEmptyOptional, ErrorSetEmptyOptional, Lazy, LazyAsync, LazyDictionary, Logger, NEVER, NonExhaustiveSwitchError, Operation, OperationAggregateError, Optional, PredicateBuilder, RandomTimeDuration, RateThrottler, Semaphore, Sorter, StringParts, TimeDuration, TimeFrequency, TimeInstant, TimeRange, TimeUnit, TimeoutError, alwaysFalse, alwaysTrue, and, arrayGet, arrayIncludes, asError, asPromise, average, averageBy, awaitAtMost, capitalizeWord, clamp, clampInt0_100, constant, constantFalse, constantNull, constantOne, constantTrue, constantUndefined, constantZero, cssDeclarationRulesDictionaryToCss, decrement, decrementBy, delayPromise, dictToEntries, dictToList, divideBy, ellipsis, ensureArray, ensureDefined, ensureNegativeNumber, ensureNonNegativeNumber, ensureNonPositiveNumber, ensurePositiveNumber, ensureReadableArray, entriesToDict, entriesToEntries, entriesToList, extendArray, extendArrayWith, fill, fillWith, filterMap, filterMapReduce, filterWithTypePredicate, findInArray, findIndexInArray, first, flatMapTruthys, getCauseMessageFromError, getCauseStackFromError, getMessageFromError, getStackFromError, groupByBoolean, groupByBooleanWith, groupByNumber, groupByNumberWith, groupByString, groupByStringWith, groupBySymbol, groupBySymbolWith, hashCode, havingMaxBy, havingMinBy, head, identity, ifDefined, ifNullOrUndefined, iff, includes, increment, incrementBy, indexByNumber, indexByNumberWith, indexByString, indexByStringWith, indexBySymbol, indexBySymbolWith, indexByWith, isAllowedTimeDuration, isArray, isDefined, isEmpty, isError, isFalse, isFunction, isNegativeNumber, isNullOrUndefined, isNullOrUndefinedOrEmpty, isNumber, isPositiveNumber, isString, isTimeInstant, isTrue, isUpgradable, isZero, jsonCloneDeep, last, listToDict, mapDefined, mapEntries, mapFirstTruthy, mapTruthys, max, maxBy, min, minBy, multiplyBy, noop, not, omitFromJsonObject, or, pad, padLeft, padRight, parseJson, parseTimeInstantBasicComponents, parseTimeInstantComponents, partition, pick, pipedInvoke, pipedInvokeFromArray, pluralize, promiseSequence, randomDecimalInInterval, randomId, randomIntegerInInterval, randomNumberInInterval, randomPick, randomPicks, range, repeat, reverse, round, roundAwayFromZero, roundToLower, roundToNearest, roundToUpper, roundTowardsZero, shallowArrayEquals, shallowRecordEquals, sortedArray, splitWords, stringToNumber, stringifyJson, sum, sumBy, tail, throttle, throwIfNullOrUndefined, transformCssDictionary, tryToParseJson, tryToParseNumber, uniq, uniqBy, uniqByKey, unzip, upsert, withTryCatch, withTryCatchAsync, wrapWithString, xor, zip };
|
|
1606
1791
|
export type { ICancelable, ICancelablePromise, IDataUpgrader, TAccumulator, TAllKeysOptional, TAnyFunction, TArrayable, TAsyncAnyFunction, TAsyncBiConsumer, TAsyncBiFunction, TAsyncBiPredicate, TAsyncConsumer, TAsyncFunction, TAsyncOperation, TAsyncOperationTuple, TAsyncPredicate, TAsyncProducer, TAsyncValidation, TAsyncVoidFunction, TBasicTimePattern, TBiConsumer, TBiFunction, TBiPredicate, TComparisonDirection, TComparisonFunction, TComparisonResult, TConditionalOptionalType, TConditionalParameter, TConditionalParameterOptions, TConsumer, TCssDeclarationRulesDictionary, TCssSelectorDeclarationRulesDictionary, TDayOfMonth, TDayOfWeek, TDigit, TDigit1_9, TEmpty, TEmptyArray, TEmptyObject, TEmptyOptional, TFourDigits, TFourDigitsMillisecond, TFourDigitsYear, TFunction, THasNever, THourOfDay, THtmlString, TIdentityFunction, TIntervalHandle, TIsEmptyObject, TIso8601DateString, TIso8601DateUtcString, TJsonArray, TJsonObject, TJsonPrimitive, TJsonSerializable, TKeysOfType, TLoggerOpts, TMaybe, TMillisecondOfSecond, TMinuteOfHour, TMonth, TMonthName, TNegativeNumber, TNumber0_10, TNumber0_100, TNumber0_1000, TNumber0_15, TNumber0_20, TNumber0_5, TNumber1_10, TNumericFloatingPointString, TNumericString, TOneDigit, TOperation, TOperationFailure, TOperationSuccess, TOperationTuple, TOptional, TOptionalKeysForType, TOptionsWithoutDefaults, TParseInt, TParseableInt, TPositiveNumber, TPredefinedTimeDuration, TPredicate, TPresentOptional, TPrettify, TPrimitive, TProducer, TPromisable, TReadableArray, TRelativeUrl, TReplaceType, TRequiredKeysForType, TSecondOfMinute, TSorter, TSorterBuilder, TStrictComparisonResult, TThreeDigits, TThreeDigitsMillisecond, TTimeInUnits, TTimeoutHandle, TTransformer, TTwoDigits, TTwoDigitsDate, TTwoDigitsHour, TTwoDigitsMinute, TTwoDigitsMonth, TTwoDigitsSecond, TTypePredicate, TUpToFourDigits, TUpToThreeDigits, TUpToTwoDigits, TUpgradable, TUrl, TValidTimeDuration, TValidation, TVoidFunction, TWeekNumber, TWithExtras, TWithRequiredProperties, TWithRequiredProperty, TYear, TZero };
|
package/.rollup/index.mjs
CHANGED
|
@@ -1359,6 +1359,31 @@ const Operation = {
|
|
|
1359
1359
|
partition: (results) => {
|
|
1360
1360
|
return partition(results, r => r.success);
|
|
1361
1361
|
},
|
|
1362
|
+
/**
|
|
1363
|
+
* Transforms the success value of an operation using the provided function.
|
|
1364
|
+
* If the operation is a failure, it is returned unchanged (same reference).
|
|
1365
|
+
* The transformation function is never called on a failure.
|
|
1366
|
+
*
|
|
1367
|
+
* @template T - The input success data type
|
|
1368
|
+
* @template U - The output success data type
|
|
1369
|
+
* @template E - The error type (preserved exactly)
|
|
1370
|
+
* @param op - The operation result to transform
|
|
1371
|
+
* @param fn - Pure function applied to the success value
|
|
1372
|
+
* @returns A new success with the transformed value, or the original failure
|
|
1373
|
+
*
|
|
1374
|
+
* @example
|
|
1375
|
+
* Operation.map(Operation.ok(1), x => x * 2);
|
|
1376
|
+
* // => { success: true, data: 2 }
|
|
1377
|
+
*
|
|
1378
|
+
* Operation.map(Operation.ko('err'), x => x * 2);
|
|
1379
|
+
* // => { success: false, error: 'err' }
|
|
1380
|
+
*/
|
|
1381
|
+
map: (op, fn) => {
|
|
1382
|
+
if (op.success) {
|
|
1383
|
+
return { success: true, data: fn(op.data) };
|
|
1384
|
+
}
|
|
1385
|
+
return op;
|
|
1386
|
+
},
|
|
1362
1387
|
combine: combine$1,
|
|
1363
1388
|
};
|
|
1364
1389
|
|
|
@@ -3689,11 +3714,70 @@ function printTransitions(transitions) {
|
|
|
3689
3714
|
}
|
|
3690
3715
|
|
|
3691
3716
|
const VERSION_FIELD = "$version";
|
|
3717
|
+
/**
|
|
3718
|
+
* Versioned data migration system for transparently upgrading serialized data to the latest version.
|
|
3719
|
+
*
|
|
3720
|
+
* DataUpgrader manages the migration of data structures across multiple versions, automatically
|
|
3721
|
+
* finding the shortest upgrade path and applying transformations. This is particularly useful for
|
|
3722
|
+
* handling persisted data that may be in any historical format.
|
|
3723
|
+
*
|
|
3724
|
+
* **Key Use Case:** Reading serialized data of unknown version and migrating it transparently.
|
|
3725
|
+
*
|
|
3726
|
+
* @example
|
|
3727
|
+
* ```typescript
|
|
3728
|
+
* // Step 1: Define all historical versions with $version discriminator
|
|
3729
|
+
* type TSerializedData_V1 = { name: string; $version: 1 };
|
|
3730
|
+
* type TSerializedData_V2 = { name: string; age: number; $version: 2 };
|
|
3731
|
+
* type TSerializedData_V3 = { name: string; age: number; email: string; $version: 3 };
|
|
3732
|
+
*
|
|
3733
|
+
* // Step 2: Create union type and current version type
|
|
3734
|
+
* type TSerializedData_Vstar = TSerializedData_V1 | TSerializedData_V2 | TSerializedData_V3;
|
|
3735
|
+
* type TSerializedData = TSerializedData_V3;
|
|
3736
|
+
*
|
|
3737
|
+
* // Step 3: Create upgrader with transition functions
|
|
3738
|
+
* const upgrader = DataUpgrader.create<TSerializedData_Vstar, TSerializedData>(3)
|
|
3739
|
+
* .addTransition(1, 2, async (data: TSerializedData_V1) => ({
|
|
3740
|
+
* ...data,
|
|
3741
|
+
* age: 0,
|
|
3742
|
+
* $version: 2
|
|
3743
|
+
* }))
|
|
3744
|
+
* .addTransition(2, 3, async (data: TSerializedData_V2) => ({
|
|
3745
|
+
* ...data,
|
|
3746
|
+
* email: "",
|
|
3747
|
+
* $version: 3
|
|
3748
|
+
* }))
|
|
3749
|
+
* .addTransition(1, 3, async (data: TSerializedData_V1) => ({
|
|
3750
|
+
* // Optional: Direct path for efficiency
|
|
3751
|
+
* ...data,
|
|
3752
|
+
* age: 0,
|
|
3753
|
+
* email: "",
|
|
3754
|
+
* $version: 3
|
|
3755
|
+
* }));
|
|
3756
|
+
*
|
|
3757
|
+
* // Step 4: Use in data loading - handles any version transparently
|
|
3758
|
+
* async function loadData(json: string): Promise<TSerializedData> {
|
|
3759
|
+
* const data = parseJson<TSerializedData_Vstar>(json);
|
|
3760
|
+
* return await upgrader.upgrade(data);
|
|
3761
|
+
* }
|
|
3762
|
+
*
|
|
3763
|
+
* // Works with any version:
|
|
3764
|
+
* const v1 = await loadData('{"name":"Alice","$version":1}'); // → V3
|
|
3765
|
+
* const v2 = await loadData('{"name":"Bob","age":25,"$version":2}'); // → V3
|
|
3766
|
+
* const v3 = await loadData('{"name":"Carol","age":30,"email":"c@example.com","$version":3}'); // → V3
|
|
3767
|
+
* ```
|
|
3768
|
+
*
|
|
3769
|
+
* @typeParam X - Union type of all possible data versions (must extend TUpgradable)
|
|
3770
|
+
* @typeParam XLatest - The latest version type (must extend X)
|
|
3771
|
+
*
|
|
3772
|
+
* @see {@link isUpgradable | Type guard for checking if data is upgradable}
|
|
3773
|
+
* @see {@link DataUpgrader.Errors | Error types for upgrade failures}
|
|
3774
|
+
*/
|
|
3692
3775
|
class DataUpgrader {
|
|
3693
3776
|
latestVersion;
|
|
3694
|
-
transitions
|
|
3695
|
-
constructor(latestVersion) {
|
|
3777
|
+
transitions;
|
|
3778
|
+
constructor(latestVersion, transitions = {}) {
|
|
3696
3779
|
this.latestVersion = latestVersion;
|
|
3780
|
+
this.transitions = transitions;
|
|
3697
3781
|
}
|
|
3698
3782
|
addTransition(from, to, apply) {
|
|
3699
3783
|
if (from === undefined || from < 0)
|
|
@@ -3740,6 +3824,17 @@ class DataUpgrader {
|
|
|
3740
3824
|
static create(latest) {
|
|
3741
3825
|
return new DataUpgrader(latest);
|
|
3742
3826
|
}
|
|
3827
|
+
/**
|
|
3828
|
+
* Creates a DataUpgrader from a DataUpgraderBuilder instance.
|
|
3829
|
+
* @internal
|
|
3830
|
+
*/
|
|
3831
|
+
static fromBuilder(builder, latestVersion) {
|
|
3832
|
+
// Extract transitions from builder and convert to strongly-typed TTransitionMatrix
|
|
3833
|
+
// This type assertion is safe because the builder has validated all transitions
|
|
3834
|
+
// at compile-time via its type parameters
|
|
3835
|
+
const transitions = builder.getTransitions();
|
|
3836
|
+
return new DataUpgrader(latestVersion, transitions);
|
|
3837
|
+
}
|
|
3743
3838
|
static Errors = {
|
|
3744
3839
|
EmptyUpgrade: EmptyUpgradeError,
|
|
3745
3840
|
UnavailableUpgrade: UnavailableUpgradeError
|
|
@@ -3748,6 +3843,142 @@ class DataUpgrader {
|
|
|
3748
3843
|
function isUpgradable(obj) {
|
|
3749
3844
|
return isDefined(obj) && typeof obj === "object" && VERSION_FIELD in obj && isNumber(obj.$version) && isPositiveNumber(obj.$version);
|
|
3750
3845
|
}
|
|
3846
|
+
/**
|
|
3847
|
+
* The current system is unable to catch the following problems at compile-time:
|
|
3848
|
+
* type A_V1 = { a: number, $version: 1 }
|
|
3849
|
+
* type A_V2 = { a: number, b: number, $version: 2 }
|
|
3850
|
+
* type A_V3 = { a: number, b: number, c: string, $version: 3 }
|
|
3851
|
+
* type A_Vstar = A_V1 | A_V2 | A_V3;
|
|
3852
|
+
* type A = A_V3;
|
|
3853
|
+
*
|
|
3854
|
+
* const DU1 = DataUpgrader.create<A_Vstar, A>( 3 );
|
|
3855
|
+
*
|
|
3856
|
+
* const DU2 = DataUpgrader.create<A_Vstar, A>( 3 )
|
|
3857
|
+
* .addTransition( 1, 3, x => ( { ...x, b: 2, c: "foo", $version: 3 } ) )
|
|
3858
|
+
* .addTransition( 1, 3, x => ( { ...x, b: 3, c: "bar", $version: 3 } ) )
|
|
3859
|
+
* ;
|
|
3860
|
+
*
|
|
3861
|
+
* const DU3 = DataUpgrader.create<A_Vstar, A>( 3 )
|
|
3862
|
+
* .addTransition( 1, 2, x => ( { ...x, b: 2, $version: 2 } ) )
|
|
3863
|
+
* .addTransition( 2, 1, x => ( { ...x, $version: 1 } ) )
|
|
3864
|
+
* ;
|
|
3865
|
+
*/
|
|
3866
|
+
|
|
3867
|
+
/**
|
|
3868
|
+
* Builder for creating type-safe DataUpgrader instances with compile-time safety.
|
|
3869
|
+
*
|
|
3870
|
+
* Prevents at compile-time:
|
|
3871
|
+
* - Missing upgrade paths (incomplete version coverage)
|
|
3872
|
+
* - Duplicate transition definitions
|
|
3873
|
+
* - Backward transitions (e.g., version 2 → 1)
|
|
3874
|
+
*
|
|
3875
|
+
* @example
|
|
3876
|
+
* ```typescript
|
|
3877
|
+
* // Step 1: Define all historical versions with $version discriminator
|
|
3878
|
+
* type V1 = { name: string; $version: 1 };
|
|
3879
|
+
* type V2 = { name: string; age: number; $version: 2 };
|
|
3880
|
+
* type V3 = { name: string; age: number; email: string; $version: 3 };
|
|
3881
|
+
*
|
|
3882
|
+
* // Step 2: Build the upgrader with type-safe transitions
|
|
3883
|
+
* const upgrader = DataUpgraderBuilder.start<V1>()
|
|
3884
|
+
* .addTransition<V2>(2, async (data) => ({
|
|
3885
|
+
* ...data,
|
|
3886
|
+
* age: 0,
|
|
3887
|
+
* $version: 2
|
|
3888
|
+
* }))
|
|
3889
|
+
* .addTransition<V3>(3, async (data) => ({
|
|
3890
|
+
* ...data,
|
|
3891
|
+
* email: "",
|
|
3892
|
+
* $version: 3
|
|
3893
|
+
* }))
|
|
3894
|
+
* .addShortcut<V1, V3>(1, 3, async (data) => ({
|
|
3895
|
+
* // Optional: Direct path for efficiency
|
|
3896
|
+
* ...data,
|
|
3897
|
+
* age: 0,
|
|
3898
|
+
* email: "",
|
|
3899
|
+
* $version: 3
|
|
3900
|
+
* }))
|
|
3901
|
+
* .build(3);
|
|
3902
|
+
*
|
|
3903
|
+
* // Step 3: Use the upgrader
|
|
3904
|
+
* async function loadData(json: string): Promise<V3> {
|
|
3905
|
+
* const data = JSON.parse(json);
|
|
3906
|
+
* return await upgrader.upgrade(data);
|
|
3907
|
+
* }
|
|
3908
|
+
*
|
|
3909
|
+
* // Works with any version:
|
|
3910
|
+
* const v1 = await loadData('{"name":"Alice","$version":1}'); // → V3
|
|
3911
|
+
* const v2 = await loadData('{"name":"Bob","age":25,"$version":2}'); // → V3
|
|
3912
|
+
* const v3 = await loadData('{"name":"Carol","age":30,"email":"c@example.com","$version":3}'); // → V3
|
|
3913
|
+
* ```
|
|
3914
|
+
*/
|
|
3915
|
+
class DataUpgraderBuilder {
|
|
3916
|
+
latestVersion;
|
|
3917
|
+
transitions;
|
|
3918
|
+
constructor(latestVersion, transitions = {}) {
|
|
3919
|
+
this.latestVersion = latestVersion;
|
|
3920
|
+
this.transitions = transitions;
|
|
3921
|
+
}
|
|
3922
|
+
/** Starts building a new DataUpgrader from the lowest version. */
|
|
3923
|
+
static start() {
|
|
3924
|
+
return new DataUpgraderBuilder(1);
|
|
3925
|
+
}
|
|
3926
|
+
/**
|
|
3927
|
+
* Adds a sequential transition from the current latest version to a new version.
|
|
3928
|
+
* Only the new version type needs to be specified.
|
|
3929
|
+
*
|
|
3930
|
+
* @example
|
|
3931
|
+
* ```typescript
|
|
3932
|
+
* builder.addTransition<V2>(2, async (d) => ({ ...d, extra: 0, $version: 2 }))
|
|
3933
|
+
* ```
|
|
3934
|
+
*/
|
|
3935
|
+
addTransition(toVersion, apply) {
|
|
3936
|
+
const newTransitions = {
|
|
3937
|
+
...this.transitions,
|
|
3938
|
+
[toVersion]: {
|
|
3939
|
+
...(this.transitions[toVersion] ?? {}),
|
|
3940
|
+
[this.latestVersion]: { from: this.latestVersion, to: toVersion, apply: async (d) => apply(d) }
|
|
3941
|
+
}
|
|
3942
|
+
};
|
|
3943
|
+
const builder = new DataUpgraderBuilder(toVersion, newTransitions);
|
|
3944
|
+
return builder;
|
|
3945
|
+
}
|
|
3946
|
+
/**
|
|
3947
|
+
* Adds a shortcut transition between arbitrary versions.
|
|
3948
|
+
* Both versions must already be in the accumulated union type.
|
|
3949
|
+
*
|
|
3950
|
+
* @example
|
|
3951
|
+
* ```typescript
|
|
3952
|
+
* builder.addShortcut<V1, V3>(1, 3, async (d) => ({ ...d, extra: 0, flag: false, $version: 3 }))
|
|
3953
|
+
* ```
|
|
3954
|
+
*/
|
|
3955
|
+
addShortcut(fromVersion, toVersion, apply) {
|
|
3956
|
+
const newTransitions = {
|
|
3957
|
+
...this.transitions,
|
|
3958
|
+
[toVersion]: {
|
|
3959
|
+
...(this.transitions[toVersion] ?? {}),
|
|
3960
|
+
[fromVersion]: { from: fromVersion, to: toVersion, apply: async (d) => apply(d) }
|
|
3961
|
+
}
|
|
3962
|
+
};
|
|
3963
|
+
const builder = new DataUpgraderBuilder(this.latestVersion, newTransitions);
|
|
3964
|
+
return builder;
|
|
3965
|
+
}
|
|
3966
|
+
/**
|
|
3967
|
+
* Builds the DataUpgrader with the current latest version.
|
|
3968
|
+
*
|
|
3969
|
+
* @example
|
|
3970
|
+
* ```typescript
|
|
3971
|
+
* const upgrader = builder.build(3);
|
|
3972
|
+
* ```
|
|
3973
|
+
*/
|
|
3974
|
+
build(latestVersion) {
|
|
3975
|
+
return DataUpgrader.fromBuilder(this, latestVersion);
|
|
3976
|
+
}
|
|
3977
|
+
/** @internal */
|
|
3978
|
+
getTransitions() {
|
|
3979
|
+
return this.transitions;
|
|
3980
|
+
}
|
|
3981
|
+
}
|
|
3751
3982
|
|
|
3752
|
-
export { Cached, DataUpgrader, Deferred, DeferredCanceledError, ErrorCannotInstantiatePresentOptionalWithEmptyValue, ErrorGetEmptyOptional, ErrorSetEmptyOptional, Lazy, LazyAsync, LazyDictionary, Logger, NEVER, NonExhaustiveSwitchError, Operation, OperationAggregateError, Optional, PredicateBuilder, RandomTimeDuration, RateThrottler, Semaphore, Sorter, StringParts, TimeDuration, TimeFrequency, TimeInstant, TimeRange, TimeUnit, TimeoutError, alwaysFalse, alwaysTrue, and, arrayGet, arrayIncludes, asError, asPromise, average, averageBy, awaitAtMost, capitalizeWord, clamp, clampInt0_100, constant, constantFalse, constantNull, constantOne, constantTrue, constantUndefined, constantZero, cssDeclarationRulesDictionaryToCss, decrement, decrementBy, delayPromise, dictToEntries, dictToList, divideBy, ellipsis, ensureArray, ensureDefined, ensureNegativeNumber, ensureNonNegativeNumber, ensureNonPositiveNumber, ensurePositiveNumber, ensureReadableArray, entriesToDict, entriesToEntries, entriesToList, extendArray, extendArrayWith, fill, fillWith, filterMap, filterMapReduce, filterWithTypePredicate, findInArray, findIndexInArray, first$1 as first, flatMapTruthys, getCauseMessageFromError, getCauseStackFromError, getMessageFromError, getStackFromError, groupByBoolean, groupByBooleanWith, groupByNumber, groupByNumberWith, groupByString, groupByStringWith, groupBySymbol, groupBySymbolWith, hashCode, havingMaxBy, havingMinBy, head, identity, ifDefined, ifNullOrUndefined, iff, includes, increment, incrementBy, indexByNumber, indexByNumberWith, indexByString, indexByStringWith, indexBySymbol, indexBySymbolWith, indexByWith, isAllowedTimeDuration, isArray, isDefined, isEmpty, isError, isFalse, isFunction, isNegativeNumber, isNullOrUndefined, isNullOrUndefinedOrEmpty, isNumber, isPositiveNumber, isString, isTimeInstant, isTrue, isUpgradable, isZero, jsonCloneDeep, last$1 as last, listToDict, mapDefined, mapEntries, mapFirstTruthy, mapTruthys, max, maxBy, min, minBy, multiplyBy, noop, not, omitFromJsonObject, or, pad, padLeft, padRight, parseJson, parseTimeInstantBasicComponents, parseTimeInstantComponents, partition, pick, pipedInvoke, pipedInvokeFromArray, pluralize, promiseSequence, randomDecimalInInterval, randomId, randomIntegerInInterval, randomNumberInInterval, randomPick, randomPicks, range, repeat, reverse$1 as reverse, round, roundAwayFromZero, roundToLower, roundToNearest, roundToUpper, roundTowardsZero, shallowArrayEquals, shallowRecordEquals, sortedArray, splitWords, stringToNumber, stringifyJson, sum, sumBy, tail, throttle, throwIfNullOrUndefined, transformCssDictionary, tryToParseJson, tryToParseNumber, uniq, uniqBy, uniqByKey, unzip, upsert, withTryCatch, withTryCatchAsync, wrapWithString, xor, zip };
|
|
3983
|
+
export { Cached, DataUpgrader, DataUpgraderBuilder, Deferred, DeferredCanceledError, ErrorCannotInstantiatePresentOptionalWithEmptyValue, ErrorGetEmptyOptional, ErrorSetEmptyOptional, Lazy, LazyAsync, LazyDictionary, Logger, NEVER, NonExhaustiveSwitchError, Operation, OperationAggregateError, Optional, PredicateBuilder, RandomTimeDuration, RateThrottler, Semaphore, Sorter, StringParts, TimeDuration, TimeFrequency, TimeInstant, TimeRange, TimeUnit, TimeoutError, alwaysFalse, alwaysTrue, and, arrayGet, arrayIncludes, asError, asPromise, average, averageBy, awaitAtMost, capitalizeWord, clamp, clampInt0_100, constant, constantFalse, constantNull, constantOne, constantTrue, constantUndefined, constantZero, cssDeclarationRulesDictionaryToCss, decrement, decrementBy, delayPromise, dictToEntries, dictToList, divideBy, ellipsis, ensureArray, ensureDefined, ensureNegativeNumber, ensureNonNegativeNumber, ensureNonPositiveNumber, ensurePositiveNumber, ensureReadableArray, entriesToDict, entriesToEntries, entriesToList, extendArray, extendArrayWith, fill, fillWith, filterMap, filterMapReduce, filterWithTypePredicate, findInArray, findIndexInArray, first$1 as first, flatMapTruthys, getCauseMessageFromError, getCauseStackFromError, getMessageFromError, getStackFromError, groupByBoolean, groupByBooleanWith, groupByNumber, groupByNumberWith, groupByString, groupByStringWith, groupBySymbol, groupBySymbolWith, hashCode, havingMaxBy, havingMinBy, head, identity, ifDefined, ifNullOrUndefined, iff, includes, increment, incrementBy, indexByNumber, indexByNumberWith, indexByString, indexByStringWith, indexBySymbol, indexBySymbolWith, indexByWith, isAllowedTimeDuration, isArray, isDefined, isEmpty, isError, isFalse, isFunction, isNegativeNumber, isNullOrUndefined, isNullOrUndefinedOrEmpty, isNumber, isPositiveNumber, isString, isTimeInstant, isTrue, isUpgradable, isZero, jsonCloneDeep, last$1 as last, listToDict, mapDefined, mapEntries, mapFirstTruthy, mapTruthys, max, maxBy, min, minBy, multiplyBy, noop, not, omitFromJsonObject, or, pad, padLeft, padRight, parseJson, parseTimeInstantBasicComponents, parseTimeInstantComponents, partition, pick, pipedInvoke, pipedInvokeFromArray, pluralize, promiseSequence, randomDecimalInInterval, randomId, randomIntegerInInterval, randomNumberInInterval, randomPick, randomPicks, range, repeat, reverse$1 as reverse, round, roundAwayFromZero, roundToLower, roundToNearest, roundToUpper, roundTowardsZero, shallowArrayEquals, shallowRecordEquals, sortedArray, splitWords, stringToNumber, stringifyJson, sum, sumBy, tail, throttle, throwIfNullOrUndefined, transformCssDictionary, tryToParseJson, tryToParseNumber, uniq, uniqBy, uniqByKey, unzip, upsert, withTryCatch, withTryCatchAsync, wrapWithString, xor, zip };
|
|
3753
3984
|
//# sourceMappingURL=index.mjs.map
|