@oscarpalmer/atoms 0.197.0 → 0.198.0
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/dist/index.d.mts +735 -708
- package/dist/index.mjs +83 -66
- package/dist/value/clone.d.mts +40 -13
- package/dist/value/clone.mjs +82 -65
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -3412,33 +3412,22 @@ Object.defineProperty(template, "initialize", { value: initializeTemplater });
|
|
|
3412
3412
|
//#region src/value/clone.ts
|
|
3413
3413
|
const CLONE_NAME = "clone";
|
|
3414
3414
|
function clone(value, options) {
|
|
3415
|
-
|
|
3416
|
-
case value === null:
|
|
3417
|
-
case value === void 0:
|
|
3418
|
-
case typeof value === "bigint":
|
|
3419
|
-
case typeof value === "boolean":
|
|
3420
|
-
case typeof value === "number":
|
|
3421
|
-
case typeof value === "string": return value;
|
|
3422
|
-
case value instanceof Date: return new Date(value.getTime());
|
|
3423
|
-
default: return cloneAny(value, getCloneParameters(options), 0);
|
|
3424
|
-
}
|
|
3415
|
+
return cloneAny(value, { copy: false }, 0, options);
|
|
3425
3416
|
}
|
|
3426
|
-
|
|
3427
|
-
callback: tryStructuredClone,
|
|
3428
|
-
method: CLONE_NAME
|
|
3429
|
-
});
|
|
3430
|
-
clone.deregister = deregisterCloner;
|
|
3431
|
-
clone.register = registerCloner;
|
|
3432
|
-
function cloneAny(value, parameters, depth) {
|
|
3417
|
+
function cloneAny(value, parameters, depth, options) {
|
|
3433
3418
|
switch (true) {
|
|
3434
|
-
case value
|
|
3435
|
-
case typeof value === "bigint":
|
|
3436
|
-
case typeof value === "boolean":
|
|
3437
|
-
case typeof value === "number":
|
|
3438
|
-
case typeof value === "string": return value;
|
|
3419
|
+
case value === null || CLONE_PRIMITIVES[typeof value]: return value;
|
|
3439
3420
|
case value instanceof Date: return new Date(value.getTime());
|
|
3440
|
-
case typeof value === "function":
|
|
3441
|
-
|
|
3421
|
+
case typeof value === "function":
|
|
3422
|
+
parameters.options ??= getCloneOptions(options);
|
|
3423
|
+
return parameters.options.copyFunctions ? value : void 0;
|
|
3424
|
+
case typeof value === "symbol":
|
|
3425
|
+
parameters.options ??= getCloneOptions(options);
|
|
3426
|
+
return parameters.options.copySymbols ? value : Symbol(value.description);
|
|
3427
|
+
}
|
|
3428
|
+
parameters.options ??= getCloneOptions(options);
|
|
3429
|
+
parameters.references ??= /* @__PURE__ */ new WeakMap();
|
|
3430
|
+
switch (true) {
|
|
3442
3431
|
case parameters.references.has(value): return parameters.references.get(value);
|
|
3443
3432
|
case value instanceof ArrayBuffer: return cloneArrayBuffer(value, parameters, depth);
|
|
3444
3433
|
case value instanceof DataView: return cloneDataView(value, parameters, depth);
|
|
@@ -3448,18 +3437,18 @@ function cloneAny(value, parameters, depth) {
|
|
|
3448
3437
|
case value instanceof Set: return cloneSet(value, parameters, depth);
|
|
3449
3438
|
case isArrayOrPlainObject(value): return cloneObject(value, parameters, depth);
|
|
3450
3439
|
case isTypedArray(value): return cloneTypedArray(value, parameters, depth);
|
|
3451
|
-
default: return clone.handlers.handle(value, parameters, depth);
|
|
3440
|
+
default: return parameters.copy ? value : clone.handlers.handle(value, parameters, depth);
|
|
3452
3441
|
}
|
|
3453
3442
|
}
|
|
3454
3443
|
function cloneArrayBuffer(value, parameters, depth) {
|
|
3455
|
-
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
3444
|
+
if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
|
|
3456
3445
|
const cloned = new ArrayBuffer(value.byteLength);
|
|
3457
3446
|
new Uint8Array(cloned).set(new Uint8Array(value));
|
|
3458
3447
|
parameters.references.set(value, cloned);
|
|
3459
3448
|
return cloned;
|
|
3460
3449
|
}
|
|
3461
3450
|
function cloneDataView(value, parameters, depth) {
|
|
3462
|
-
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
3451
|
+
if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
|
|
3463
3452
|
const buffer = cloneArrayBuffer(value.buffer, parameters, depth);
|
|
3464
3453
|
const cloned = new DataView(buffer, value.byteOffset, value.byteLength);
|
|
3465
3454
|
parameters.references.set(value, cloned);
|
|
@@ -3467,22 +3456,22 @@ function cloneDataView(value, parameters, depth) {
|
|
|
3467
3456
|
}
|
|
3468
3457
|
function cloneMap(map, parameters, depth) {
|
|
3469
3458
|
if (depth >= CLONE_MAX_DEPTH) return map;
|
|
3470
|
-
|
|
3459
|
+
if (parameters.copy) return new Map(map);
|
|
3471
3460
|
const cloned = /* @__PURE__ */ new Map();
|
|
3472
|
-
const
|
|
3473
|
-
for (const entry of entries) cloned.set(flat ? entry[0] : cloneAny(entry[0], parameters, depth + 1), flat ? entry[1] : cloneAny(entry[1], parameters, depth + 1));
|
|
3461
|
+
for (const [key, value] of map.entries()) cloned.set(cloneAny(key, parameters, depth + 1), cloneAny(value, parameters, depth + 1));
|
|
3474
3462
|
parameters.references.set(map, cloned);
|
|
3475
3463
|
return cloned;
|
|
3476
3464
|
}
|
|
3477
3465
|
function cloneNode(node, parameters, depth) {
|
|
3478
|
-
if (depth >= CLONE_MAX_DEPTH) return node;
|
|
3466
|
+
if (parameters.copy || depth >= CLONE_MAX_DEPTH) return node;
|
|
3479
3467
|
const cloned = node.cloneNode(true);
|
|
3480
3468
|
parameters.references.set(node, cloned);
|
|
3481
3469
|
return cloned;
|
|
3482
3470
|
}
|
|
3483
3471
|
function cloneObject(value, parameters, depth) {
|
|
3472
|
+
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
3484
3473
|
const isArray = Array.isArray(value);
|
|
3485
|
-
if (parameters.
|
|
3474
|
+
if (parameters.copy) return isArray ? value.slice() : { ...value };
|
|
3486
3475
|
const cloned = isArray ? [] : {};
|
|
3487
3476
|
const keys = isArray ? void 0 : Object.keys(value);
|
|
3488
3477
|
const { length } = keys ?? value;
|
|
@@ -3494,7 +3483,7 @@ function cloneObject(value, parameters, depth) {
|
|
|
3494
3483
|
return cloned;
|
|
3495
3484
|
}
|
|
3496
3485
|
function cloneRegularExpression(value, parameters, depth) {
|
|
3497
|
-
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
3486
|
+
if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
|
|
3498
3487
|
const cloned = new RegExp(value.source, value.flags);
|
|
3499
3488
|
cloned.lastIndex = value.lastIndex;
|
|
3500
3489
|
parameters.references.set(value, cloned);
|
|
@@ -3502,30 +3491,24 @@ function cloneRegularExpression(value, parameters, depth) {
|
|
|
3502
3491
|
}
|
|
3503
3492
|
function cloneSet(set, parameters, depth) {
|
|
3504
3493
|
if (depth >= CLONE_MAX_DEPTH) return set;
|
|
3494
|
+
if (parameters.copy) return new Set(set);
|
|
3505
3495
|
const cloned = /* @__PURE__ */ new Set();
|
|
3506
|
-
const
|
|
3507
|
-
const { length } = values;
|
|
3508
|
-
for (let index = 0; index < length; index += 1) cloned.add(parameters.options?.flat ? values[index] : cloneAny(values[index], parameters, depth + 1));
|
|
3496
|
+
for (const value of set.values()) cloned.add(cloneAny(value, parameters, depth + 1));
|
|
3509
3497
|
parameters.references.set(set, cloned);
|
|
3510
3498
|
return cloned;
|
|
3511
3499
|
}
|
|
3512
3500
|
function cloneTypedArray(value, parameters, depth) {
|
|
3513
|
-
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
3501
|
+
if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
|
|
3514
3502
|
const cloned = new value.constructor(value);
|
|
3515
3503
|
parameters.references.set(value, cloned);
|
|
3516
3504
|
return cloned;
|
|
3517
3505
|
}
|
|
3518
|
-
/**
|
|
3519
|
-
* Copy any kind of value
|
|
3520
|
-
*
|
|
3521
|
-
* - Clones the value shallowly, without cloning nested values
|
|
3522
|
-
* - To copy a value deeply, use `clone` instead
|
|
3523
|
-
*
|
|
3524
|
-
* @param value Value to copy
|
|
3525
|
-
* @returns Copied value
|
|
3526
|
-
*/
|
|
3527
3506
|
function copy(value) {
|
|
3528
|
-
return
|
|
3507
|
+
return cloneAny(value, {
|
|
3508
|
+
copy: true,
|
|
3509
|
+
options: CLONE_COPY_OPTIONS,
|
|
3510
|
+
references: void 0
|
|
3511
|
+
}, 0);
|
|
3529
3512
|
}
|
|
3530
3513
|
/**
|
|
3531
3514
|
* Deregister a clone handler for a specific class
|
|
@@ -3538,23 +3521,35 @@ function deregisterCloner(constructor) {
|
|
|
3538
3521
|
clone.handlers.deregister(constructor);
|
|
3539
3522
|
}
|
|
3540
3523
|
function getCloneOptions(input) {
|
|
3541
|
-
if (typeof input === "boolean") return {
|
|
3542
|
-
copyFunctions: false,
|
|
3543
|
-
copySymbols: false,
|
|
3544
|
-
flat: input === true
|
|
3545
|
-
};
|
|
3546
3524
|
if (typeof input !== "object" || input === null) return CLONE_DEFAULT_OPTIONS;
|
|
3547
3525
|
return {
|
|
3548
3526
|
copyFunctions: input.copyFunctions === true,
|
|
3549
|
-
copySymbols: input.copySymbols === true
|
|
3550
|
-
flat: input.flat === true
|
|
3527
|
+
copySymbols: input.copySymbols === true
|
|
3551
3528
|
};
|
|
3552
3529
|
}
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3530
|
+
/**
|
|
3531
|
+
* Create a cloner with predefined options
|
|
3532
|
+
*
|
|
3533
|
+
* _Available as `initializeCloner` and `clone.initialize`_
|
|
3534
|
+
*
|
|
3535
|
+
* @param options Clone options
|
|
3536
|
+
* @returns Cloner function
|
|
3537
|
+
*/
|
|
3538
|
+
function initializeCloner(options) {
|
|
3539
|
+
const opts = getCloneOptions(options);
|
|
3540
|
+
function cloner(value) {
|
|
3541
|
+
return cloneAny(value, {
|
|
3542
|
+
copy: false,
|
|
3543
|
+
options: opts
|
|
3544
|
+
}, 0);
|
|
3545
|
+
}
|
|
3546
|
+
cloner.deregister = deregisterCloner;
|
|
3547
|
+
cloner.register = registerCloner;
|
|
3548
|
+
Object.defineProperties(cloner, {
|
|
3549
|
+
deregister: { value: deregisterCloner },
|
|
3550
|
+
register: { value: registerCloner }
|
|
3551
|
+
});
|
|
3552
|
+
return cloner;
|
|
3558
3553
|
}
|
|
3559
3554
|
/**
|
|
3560
3555
|
* Register a clone handler for a specific class
|
|
@@ -3571,24 +3566,46 @@ function tryStructuredClone(value, parameters, depth) {
|
|
|
3571
3566
|
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
3572
3567
|
try {
|
|
3573
3568
|
const cloned = structuredClone(value);
|
|
3574
|
-
parameters.references
|
|
3569
|
+
parameters.references.set(value, cloned);
|
|
3575
3570
|
return cloned;
|
|
3576
3571
|
} catch {
|
|
3577
|
-
parameters.references
|
|
3572
|
+
parameters.references.set(value, value);
|
|
3578
3573
|
return value;
|
|
3579
3574
|
}
|
|
3580
3575
|
}
|
|
3581
3576
|
const CLONE_COPY_OPTIONS = {
|
|
3582
3577
|
copyFunctions: true,
|
|
3583
|
-
copySymbols: true
|
|
3584
|
-
flat: true
|
|
3578
|
+
copySymbols: true
|
|
3585
3579
|
};
|
|
3586
3580
|
const CLONE_DEFAULT_OPTIONS = {
|
|
3587
3581
|
copyFunctions: false,
|
|
3588
|
-
copySymbols: false
|
|
3589
|
-
flat: false
|
|
3582
|
+
copySymbols: false
|
|
3590
3583
|
};
|
|
3591
3584
|
const CLONE_MAX_DEPTH = 100;
|
|
3585
|
+
const cloneHandlers = getSelfHandlers(clone, {
|
|
3586
|
+
callback: tryStructuredClone,
|
|
3587
|
+
method: CLONE_NAME
|
|
3588
|
+
});
|
|
3589
|
+
const CLONE_PRIMITIVES = {
|
|
3590
|
+
bigint: true,
|
|
3591
|
+
boolean: true,
|
|
3592
|
+
function: false,
|
|
3593
|
+
number: true,
|
|
3594
|
+
object: false,
|
|
3595
|
+
string: true,
|
|
3596
|
+
symbol: false,
|
|
3597
|
+
undefined: true
|
|
3598
|
+
};
|
|
3599
|
+
clone.deregister = deregisterCloner;
|
|
3600
|
+
clone.handlers = cloneHandlers;
|
|
3601
|
+
clone.initialize = initializeCloner;
|
|
3602
|
+
clone.register = registerCloner;
|
|
3603
|
+
Object.defineProperties(clone, {
|
|
3604
|
+
deregister: { value: deregisterCloner },
|
|
3605
|
+
handlers: { value: cloneHandlers },
|
|
3606
|
+
initialize: { value: initializeCloner },
|
|
3607
|
+
register: { value: registerCloner }
|
|
3608
|
+
});
|
|
3592
3609
|
//#endregion
|
|
3593
3610
|
//#region src/value/collection.ts
|
|
3594
3611
|
function inMap(map, value, key) {
|
|
@@ -6383,4 +6400,4 @@ var SizedSet = class extends Set {
|
|
|
6383
6400
|
}
|
|
6384
6401
|
};
|
|
6385
6402
|
//#endregion
|
|
6386
|
-
export { CancelablePromise, Logger, PromiseTimeoutError, QueueError, RetryError, SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING, SizedMap, SizedSet, assert, assertCondition, assertDefined, assertInstanceOf, assertIs, assertProperty, assign, asyncAttempt, asyncDebounce, asyncFlow, asyncMatchResult, asyncOnce, asyncPipe, asyncThrottle, attempt, attemptAsyncFlow, attemptAsyncPipe, attemptFlow, attemptPipe, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, copy, count, debounce, deburr, dedent, delay, deregisterCloner, deregisterComparator, deregisterEqualizer, diff, difference, drop, endsWith, endsWithArray, equal, error, exclude, exists, filter, find, findLast, first, firstOrDefault, flatFreeze, flatten, floor, flow, freeze, fromQuery, toPromise as fromResult, toPromise, fuzzy, fuzzyMatch, getArray, getArrayComparison, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getHwbColor, getHwbaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloatingNumber as getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getSortedIndex, getString, getTimedPromise, getUuid, getValue, groupArraysBy, groupBy, handleResult, hasValue, hasValueResult, herald, hexToHsl, hexToHsla, hexToHwb, hexToHwba, hexToRgb, hexToRgba, hslToHex, hslToHwb, hslToHwba, hslToRgb, hslToRgba, hwbToHex, hwbToHsl, hwbToHsla, hwbToRgb, hwbToRgba, ignoreKey, inMap, inSet, includes, includesArray, indexOf, indexOfArray, initializeAssigner, initializeEqualizer, initializeMerger, initializeNormalizer, initializeSorter, initializeTemplater, initializeTransformer, insert, interpolate, intersection, isArrayOrPlainObject, isBeacon, isBeaconSubscription, isColor, isConstructor, isEmpty, isError, isFrozen, isFulfilled, isHerald, isHeraldEvents, isHeraldSubscription, isHexColor, isHslColor, isHslaColor, isHwbColor, isHwbaColor, isInstanceOf, isKey, isKeyedQueue, isLogger, isNonArrayOrPlainObject, isNonConstructor, isNonEmpty, isNonInstanceOf, isNonKey, isNonNullable, isNonNullableOrEmpty, isNonNullableOrWhitespace, isNonNumber, isNonNumerical, isNonObject, isNonPlainObject, isNonPrimitive, isNonTypedArray, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isObservable, isOk, isPlainObject, isPrimitive, isQueue, isQueueInstance, isRejected, isResult, isRgbColor, isRgbaColor, isSorted, isSubscription, isTimedLogger, isTypedArray, join, kebabCase, keyedQueue, last, lastIndexOf, lastOrDefault, lowerCase, matchResult, max, median, memoize, merge, min, move, moveIndices, moveToIndex, noop, normalize, ok, omit, once, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, registerCloner, registerComparator, registerEqualizer, resultPromises, retry, reverse, rgbToHex, rgbToHsl, rgbToHsla, rgbToHwb, rgbToHwba, round, select, setValue, settlePromise, shake, shuffle, single, slice, smush, snakeCase, sort, splice, startsWith, startsWithArray, sum, swap, take, template, throttle, timed, times, titleCase, toMap, toMapArrays, toQuery, toRecord, toRecordArrays, toResult, toSet, toggle, transform, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };
|
|
6403
|
+
export { CancelablePromise, Logger, PromiseTimeoutError, QueueError, RetryError, SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING, SizedMap, SizedSet, assert, assertCondition, assertDefined, assertInstanceOf, assertIs, assertProperty, assign, asyncAttempt, asyncDebounce, asyncFlow, asyncMatchResult, asyncOnce, asyncPipe, asyncThrottle, attempt, attemptAsyncFlow, attemptAsyncPipe, attemptFlow, attemptPipe, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, copy, count, debounce, deburr, dedent, delay, deregisterCloner, deregisterComparator, deregisterEqualizer, diff, difference, drop, endsWith, endsWithArray, equal, error, exclude, exists, filter, find, findLast, first, firstOrDefault, flatFreeze, flatten, floor, flow, freeze, fromQuery, toPromise as fromResult, toPromise, fuzzy, fuzzyMatch, getArray, getArrayComparison, getColor, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getHwbColor, getHwbaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloatingNumber as getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getSortedIndex, getString, getTimedPromise, getUuid, getValue, groupArraysBy, groupBy, handleResult, hasValue, hasValueResult, herald, hexToHsl, hexToHsla, hexToHwb, hexToHwba, hexToRgb, hexToRgba, hslToHex, hslToHwb, hslToHwba, hslToRgb, hslToRgba, hwbToHex, hwbToHsl, hwbToHsla, hwbToRgb, hwbToRgba, ignoreKey, inMap, inSet, includes, includesArray, indexOf, indexOfArray, initializeAssigner, initializeCloner, initializeEqualizer, initializeMerger, initializeNormalizer, initializeSorter, initializeTemplater, initializeTransformer, insert, interpolate, intersection, isArrayOrPlainObject, isBeacon, isBeaconSubscription, isColor, isConstructor, isEmpty, isError, isFrozen, isFulfilled, isHerald, isHeraldEvents, isHeraldSubscription, isHexColor, isHslColor, isHslaColor, isHwbColor, isHwbaColor, isInstanceOf, isKey, isKeyedQueue, isLogger, isNonArrayOrPlainObject, isNonConstructor, isNonEmpty, isNonInstanceOf, isNonKey, isNonNullable, isNonNullableOrEmpty, isNonNullableOrWhitespace, isNonNumber, isNonNumerical, isNonObject, isNonPlainObject, isNonPrimitive, isNonTypedArray, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isObservable, isOk, isPlainObject, isPrimitive, isQueue, isQueueInstance, isRejected, isResult, isRgbColor, isRgbaColor, isSorted, isSubscription, isTimedLogger, isTypedArray, join, kebabCase, keyedQueue, last, lastIndexOf, lastOrDefault, lowerCase, matchResult, max, median, memoize, merge, min, move, moveIndices, moveToIndex, noop, normalize, ok, omit, once, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, registerCloner, registerComparator, registerEqualizer, resultPromises, retry, reverse, rgbToHex, rgbToHsl, rgbToHsla, rgbToHwb, rgbToHwba, round, select, setValue, settlePromise, shake, shuffle, single, slice, smush, snakeCase, sort, splice, startsWith, startsWithArray, sum, swap, take, template, throttle, timed, times, titleCase, toMap, toMapArrays, toQuery, toRecord, toRecordArrays, toResult, toSet, toggle, transform, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };
|
package/dist/value/clone.d.mts
CHANGED
|
@@ -9,19 +9,36 @@ type CloneOptions = {
|
|
|
9
9
|
* Copy symbols instead of returning `Symbol(description)`? _(defaults to `false`)_
|
|
10
10
|
*/
|
|
11
11
|
copySymbols?: boolean;
|
|
12
|
-
/**
|
|
13
|
-
* Clone only the value itself, without cloning nested values? _(defaults to `false`)_
|
|
14
|
-
*/
|
|
15
|
-
flat?: boolean;
|
|
16
12
|
};
|
|
17
13
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* @param value Value to clone
|
|
21
|
-
* @param flat Clone only the value itself, without cloning nested values
|
|
22
|
-
* @returns Cloned value
|
|
14
|
+
* A cloning function with predefined options
|
|
23
15
|
*/
|
|
24
|
-
|
|
16
|
+
type Cloner = {
|
|
17
|
+
/**
|
|
18
|
+
* Clone any kind of value
|
|
19
|
+
*
|
|
20
|
+
* @param value Value to clone
|
|
21
|
+
* @returns Cloned value
|
|
22
|
+
*/
|
|
23
|
+
<Value>(value: Value): Value;
|
|
24
|
+
/**
|
|
25
|
+
* Deregister a clone handler for a specific class
|
|
26
|
+
*
|
|
27
|
+
* _Available as `deregisterCloner` and `template.deregister`_
|
|
28
|
+
*
|
|
29
|
+
* @param constructor Class constructor
|
|
30
|
+
*/
|
|
31
|
+
deregister: typeof deregisterCloner;
|
|
32
|
+
/**
|
|
33
|
+
* Register a clone handler for a specific class
|
|
34
|
+
*
|
|
35
|
+
* _Available as `registerCloner` and `template.register`_
|
|
36
|
+
*
|
|
37
|
+
* @param constructor Class constructor
|
|
38
|
+
* @param handler Method name or clone function _(defaults to method name `clone`)_
|
|
39
|
+
*/
|
|
40
|
+
register: typeof registerCloner;
|
|
41
|
+
};
|
|
25
42
|
/**
|
|
26
43
|
* Clone any kind of value _(deeply, if needed)_
|
|
27
44
|
*
|
|
@@ -31,18 +48,19 @@ declare function clone<Value>(value: Value, flat: true): Value;
|
|
|
31
48
|
*/
|
|
32
49
|
declare function clone<Value>(value: Value, options?: CloneOptions): Value;
|
|
33
50
|
declare namespace clone {
|
|
51
|
+
var deregister: typeof deregisterCloner;
|
|
34
52
|
var handlers: {
|
|
35
53
|
deregister(constructor: Constructor): void;
|
|
36
54
|
handle(value: unknown, ...parameters: unknown[]): unknown;
|
|
37
55
|
register(constructor: Constructor, handler?: string | GenericCallback): void;
|
|
38
56
|
};
|
|
39
|
-
var
|
|
57
|
+
var initialize: typeof initializeCloner;
|
|
40
58
|
var register: typeof registerCloner;
|
|
41
59
|
}
|
|
42
60
|
/**
|
|
43
61
|
* Copy any kind of value
|
|
44
62
|
*
|
|
45
|
-
* -
|
|
63
|
+
* - Copies the value shallowly _(if possible)_, without copying or cloning nested values
|
|
46
64
|
* - To copy a value deeply, use `clone` instead
|
|
47
65
|
*
|
|
48
66
|
* @param value Value to copy
|
|
@@ -57,6 +75,15 @@ declare function copy<Value>(value: Value): Value;
|
|
|
57
75
|
* @param constructor Class constructor
|
|
58
76
|
*/
|
|
59
77
|
declare function deregisterCloner<Instance>(constructor: Constructor<Instance>): void;
|
|
78
|
+
/**
|
|
79
|
+
* Create a cloner with predefined options
|
|
80
|
+
*
|
|
81
|
+
* _Available as `initializeCloner` and `clone.initialize`_
|
|
82
|
+
*
|
|
83
|
+
* @param options Clone options
|
|
84
|
+
* @returns Cloner function
|
|
85
|
+
*/
|
|
86
|
+
declare function initializeCloner(options?: CloneOptions): Cloner;
|
|
60
87
|
/**
|
|
61
88
|
* Register a clone handler for a specific class
|
|
62
89
|
*
|
|
@@ -67,4 +94,4 @@ declare function deregisterCloner<Instance>(constructor: Constructor<Instance>):
|
|
|
67
94
|
*/
|
|
68
95
|
declare function registerCloner<Instance>(constructor: Constructor<Instance>, handler?: string | ((value: Instance) => Instance)): void;
|
|
69
96
|
//#endregion
|
|
70
|
-
export { CloneOptions, clone, copy, deregisterCloner, registerCloner };
|
|
97
|
+
export { CloneOptions, Cloner, clone, copy, deregisterCloner, initializeCloner, registerCloner };
|
package/dist/value/clone.mjs
CHANGED
|
@@ -3,33 +3,22 @@ import { getSelfHandlers } from "../internal/value/handlers.mjs";
|
|
|
3
3
|
//#region src/value/clone.ts
|
|
4
4
|
const CLONE_NAME = "clone";
|
|
5
5
|
function clone(value, options) {
|
|
6
|
+
return cloneAny(value, { copy: false }, 0, options);
|
|
7
|
+
}
|
|
8
|
+
function cloneAny(value, parameters, depth, options) {
|
|
6
9
|
switch (true) {
|
|
7
|
-
case value === null:
|
|
8
|
-
case value === void 0:
|
|
9
|
-
case typeof value === "bigint":
|
|
10
|
-
case typeof value === "boolean":
|
|
11
|
-
case typeof value === "number":
|
|
12
|
-
case typeof value === "string": return value;
|
|
10
|
+
case value === null || CLONE_PRIMITIVES[typeof value]: return value;
|
|
13
11
|
case value instanceof Date: return new Date(value.getTime());
|
|
14
|
-
|
|
12
|
+
case typeof value === "function":
|
|
13
|
+
parameters.options ??= getCloneOptions(options);
|
|
14
|
+
return parameters.options.copyFunctions ? value : void 0;
|
|
15
|
+
case typeof value === "symbol":
|
|
16
|
+
parameters.options ??= getCloneOptions(options);
|
|
17
|
+
return parameters.options.copySymbols ? value : Symbol(value.description);
|
|
15
18
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
callback: tryStructuredClone,
|
|
19
|
-
method: CLONE_NAME
|
|
20
|
-
});
|
|
21
|
-
clone.deregister = deregisterCloner;
|
|
22
|
-
clone.register = registerCloner;
|
|
23
|
-
function cloneAny(value, parameters, depth) {
|
|
19
|
+
parameters.options ??= getCloneOptions(options);
|
|
20
|
+
parameters.references ??= /* @__PURE__ */ new WeakMap();
|
|
24
21
|
switch (true) {
|
|
25
|
-
case value == null:
|
|
26
|
-
case typeof value === "bigint":
|
|
27
|
-
case typeof value === "boolean":
|
|
28
|
-
case typeof value === "number":
|
|
29
|
-
case typeof value === "string": return value;
|
|
30
|
-
case value instanceof Date: return new Date(value.getTime());
|
|
31
|
-
case typeof value === "function": return parameters.options?.copyFunctions ? value : void 0;
|
|
32
|
-
case typeof value === "symbol": return parameters.options?.copySymbols ? value : Symbol(value.description);
|
|
33
22
|
case parameters.references.has(value): return parameters.references.get(value);
|
|
34
23
|
case value instanceof ArrayBuffer: return cloneArrayBuffer(value, parameters, depth);
|
|
35
24
|
case value instanceof DataView: return cloneDataView(value, parameters, depth);
|
|
@@ -39,18 +28,18 @@ function cloneAny(value, parameters, depth) {
|
|
|
39
28
|
case value instanceof Set: return cloneSet(value, parameters, depth);
|
|
40
29
|
case isArrayOrPlainObject(value): return cloneObject(value, parameters, depth);
|
|
41
30
|
case isTypedArray(value): return cloneTypedArray(value, parameters, depth);
|
|
42
|
-
default: return clone.handlers.handle(value, parameters, depth);
|
|
31
|
+
default: return parameters.copy ? value : clone.handlers.handle(value, parameters, depth);
|
|
43
32
|
}
|
|
44
33
|
}
|
|
45
34
|
function cloneArrayBuffer(value, parameters, depth) {
|
|
46
|
-
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
35
|
+
if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
|
|
47
36
|
const cloned = new ArrayBuffer(value.byteLength);
|
|
48
37
|
new Uint8Array(cloned).set(new Uint8Array(value));
|
|
49
38
|
parameters.references.set(value, cloned);
|
|
50
39
|
return cloned;
|
|
51
40
|
}
|
|
52
41
|
function cloneDataView(value, parameters, depth) {
|
|
53
|
-
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
42
|
+
if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
|
|
54
43
|
const buffer = cloneArrayBuffer(value.buffer, parameters, depth);
|
|
55
44
|
const cloned = new DataView(buffer, value.byteOffset, value.byteLength);
|
|
56
45
|
parameters.references.set(value, cloned);
|
|
@@ -58,22 +47,22 @@ function cloneDataView(value, parameters, depth) {
|
|
|
58
47
|
}
|
|
59
48
|
function cloneMap(map, parameters, depth) {
|
|
60
49
|
if (depth >= CLONE_MAX_DEPTH) return map;
|
|
61
|
-
|
|
50
|
+
if (parameters.copy) return new Map(map);
|
|
62
51
|
const cloned = /* @__PURE__ */ new Map();
|
|
63
|
-
const
|
|
64
|
-
for (const entry of entries) cloned.set(flat ? entry[0] : cloneAny(entry[0], parameters, depth + 1), flat ? entry[1] : cloneAny(entry[1], parameters, depth + 1));
|
|
52
|
+
for (const [key, value] of map.entries()) cloned.set(cloneAny(key, parameters, depth + 1), cloneAny(value, parameters, depth + 1));
|
|
65
53
|
parameters.references.set(map, cloned);
|
|
66
54
|
return cloned;
|
|
67
55
|
}
|
|
68
56
|
function cloneNode(node, parameters, depth) {
|
|
69
|
-
if (depth >= CLONE_MAX_DEPTH) return node;
|
|
57
|
+
if (parameters.copy || depth >= CLONE_MAX_DEPTH) return node;
|
|
70
58
|
const cloned = node.cloneNode(true);
|
|
71
59
|
parameters.references.set(node, cloned);
|
|
72
60
|
return cloned;
|
|
73
61
|
}
|
|
74
62
|
function cloneObject(value, parameters, depth) {
|
|
63
|
+
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
75
64
|
const isArray = Array.isArray(value);
|
|
76
|
-
if (parameters.
|
|
65
|
+
if (parameters.copy) return isArray ? value.slice() : { ...value };
|
|
77
66
|
const cloned = isArray ? [] : {};
|
|
78
67
|
const keys = isArray ? void 0 : Object.keys(value);
|
|
79
68
|
const { length } = keys ?? value;
|
|
@@ -85,7 +74,7 @@ function cloneObject(value, parameters, depth) {
|
|
|
85
74
|
return cloned;
|
|
86
75
|
}
|
|
87
76
|
function cloneRegularExpression(value, parameters, depth) {
|
|
88
|
-
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
77
|
+
if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
|
|
89
78
|
const cloned = new RegExp(value.source, value.flags);
|
|
90
79
|
cloned.lastIndex = value.lastIndex;
|
|
91
80
|
parameters.references.set(value, cloned);
|
|
@@ -93,30 +82,24 @@ function cloneRegularExpression(value, parameters, depth) {
|
|
|
93
82
|
}
|
|
94
83
|
function cloneSet(set, parameters, depth) {
|
|
95
84
|
if (depth >= CLONE_MAX_DEPTH) return set;
|
|
85
|
+
if (parameters.copy) return new Set(set);
|
|
96
86
|
const cloned = /* @__PURE__ */ new Set();
|
|
97
|
-
const
|
|
98
|
-
const { length } = values;
|
|
99
|
-
for (let index = 0; index < length; index += 1) cloned.add(parameters.options?.flat ? values[index] : cloneAny(values[index], parameters, depth + 1));
|
|
87
|
+
for (const value of set.values()) cloned.add(cloneAny(value, parameters, depth + 1));
|
|
100
88
|
parameters.references.set(set, cloned);
|
|
101
89
|
return cloned;
|
|
102
90
|
}
|
|
103
91
|
function cloneTypedArray(value, parameters, depth) {
|
|
104
|
-
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
92
|
+
if (parameters.copy || depth >= CLONE_MAX_DEPTH) return value;
|
|
105
93
|
const cloned = new value.constructor(value);
|
|
106
94
|
parameters.references.set(value, cloned);
|
|
107
95
|
return cloned;
|
|
108
96
|
}
|
|
109
|
-
/**
|
|
110
|
-
* Copy any kind of value
|
|
111
|
-
*
|
|
112
|
-
* - Clones the value shallowly, without cloning nested values
|
|
113
|
-
* - To copy a value deeply, use `clone` instead
|
|
114
|
-
*
|
|
115
|
-
* @param value Value to copy
|
|
116
|
-
* @returns Copied value
|
|
117
|
-
*/
|
|
118
97
|
function copy(value) {
|
|
119
|
-
return
|
|
98
|
+
return cloneAny(value, {
|
|
99
|
+
copy: true,
|
|
100
|
+
options: CLONE_COPY_OPTIONS,
|
|
101
|
+
references: void 0
|
|
102
|
+
}, 0);
|
|
120
103
|
}
|
|
121
104
|
/**
|
|
122
105
|
* Deregister a clone handler for a specific class
|
|
@@ -129,23 +112,35 @@ function deregisterCloner(constructor) {
|
|
|
129
112
|
clone.handlers.deregister(constructor);
|
|
130
113
|
}
|
|
131
114
|
function getCloneOptions(input) {
|
|
132
|
-
if (typeof input === "boolean") return {
|
|
133
|
-
copyFunctions: false,
|
|
134
|
-
copySymbols: false,
|
|
135
|
-
flat: input === true
|
|
136
|
-
};
|
|
137
115
|
if (typeof input !== "object" || input === null) return CLONE_DEFAULT_OPTIONS;
|
|
138
116
|
return {
|
|
139
117
|
copyFunctions: input.copyFunctions === true,
|
|
140
|
-
copySymbols: input.copySymbols === true
|
|
141
|
-
flat: input.flat === true
|
|
118
|
+
copySymbols: input.copySymbols === true
|
|
142
119
|
};
|
|
143
120
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Create a cloner with predefined options
|
|
123
|
+
*
|
|
124
|
+
* _Available as `initializeCloner` and `clone.initialize`_
|
|
125
|
+
*
|
|
126
|
+
* @param options Clone options
|
|
127
|
+
* @returns Cloner function
|
|
128
|
+
*/
|
|
129
|
+
function initializeCloner(options) {
|
|
130
|
+
const opts = getCloneOptions(options);
|
|
131
|
+
function cloner(value) {
|
|
132
|
+
return cloneAny(value, {
|
|
133
|
+
copy: false,
|
|
134
|
+
options: opts
|
|
135
|
+
}, 0);
|
|
136
|
+
}
|
|
137
|
+
cloner.deregister = deregisterCloner;
|
|
138
|
+
cloner.register = registerCloner;
|
|
139
|
+
Object.defineProperties(cloner, {
|
|
140
|
+
deregister: { value: deregisterCloner },
|
|
141
|
+
register: { value: registerCloner }
|
|
142
|
+
});
|
|
143
|
+
return cloner;
|
|
149
144
|
}
|
|
150
145
|
/**
|
|
151
146
|
* Register a clone handler for a specific class
|
|
@@ -162,23 +157,45 @@ function tryStructuredClone(value, parameters, depth) {
|
|
|
162
157
|
if (depth >= CLONE_MAX_DEPTH) return value;
|
|
163
158
|
try {
|
|
164
159
|
const cloned = structuredClone(value);
|
|
165
|
-
parameters.references
|
|
160
|
+
parameters.references.set(value, cloned);
|
|
166
161
|
return cloned;
|
|
167
162
|
} catch {
|
|
168
|
-
parameters.references
|
|
163
|
+
parameters.references.set(value, value);
|
|
169
164
|
return value;
|
|
170
165
|
}
|
|
171
166
|
}
|
|
172
167
|
const CLONE_COPY_OPTIONS = {
|
|
173
168
|
copyFunctions: true,
|
|
174
|
-
copySymbols: true
|
|
175
|
-
flat: true
|
|
169
|
+
copySymbols: true
|
|
176
170
|
};
|
|
177
171
|
const CLONE_DEFAULT_OPTIONS = {
|
|
178
172
|
copyFunctions: false,
|
|
179
|
-
copySymbols: false
|
|
180
|
-
flat: false
|
|
173
|
+
copySymbols: false
|
|
181
174
|
};
|
|
182
175
|
const CLONE_MAX_DEPTH = 100;
|
|
176
|
+
const cloneHandlers = getSelfHandlers(clone, {
|
|
177
|
+
callback: tryStructuredClone,
|
|
178
|
+
method: CLONE_NAME
|
|
179
|
+
});
|
|
180
|
+
const CLONE_PRIMITIVES = {
|
|
181
|
+
bigint: true,
|
|
182
|
+
boolean: true,
|
|
183
|
+
function: false,
|
|
184
|
+
number: true,
|
|
185
|
+
object: false,
|
|
186
|
+
string: true,
|
|
187
|
+
symbol: false,
|
|
188
|
+
undefined: true
|
|
189
|
+
};
|
|
190
|
+
clone.deregister = deregisterCloner;
|
|
191
|
+
clone.handlers = cloneHandlers;
|
|
192
|
+
clone.initialize = initializeCloner;
|
|
193
|
+
clone.register = registerCloner;
|
|
194
|
+
Object.defineProperties(clone, {
|
|
195
|
+
deregister: { value: deregisterCloner },
|
|
196
|
+
handlers: { value: cloneHandlers },
|
|
197
|
+
initialize: { value: initializeCloner },
|
|
198
|
+
register: { value: registerCloner }
|
|
199
|
+
});
|
|
183
200
|
//#endregion
|
|
184
|
-
export { clone, copy, deregisterCloner, registerCloner };
|
|
201
|
+
export { clone, copy, deregisterCloner, initializeCloner, registerCloner };
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/atoms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.198.0",
|
|
4
4
|
"description": "Atomic utilities for making your JavaScript better.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"array",
|
|
7
|
+
"clone",
|
|
7
8
|
"color",
|
|
8
9
|
"helper",
|
|
9
10
|
"observable",
|
|
@@ -282,7 +283,7 @@
|
|
|
282
283
|
"@vitest/coverage-istanbul": "^4.1",
|
|
283
284
|
"eslint": "^10.9",
|
|
284
285
|
"jsdom": "^30",
|
|
285
|
-
"tsdown": "^0.
|
|
286
|
+
"tsdown": "^0.23",
|
|
286
287
|
"typescript": "^6",
|
|
287
288
|
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
|
|
288
289
|
"vite-plus": "latest",
|