@valkyriestudios/utils 12.39.0 → 12.41.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/README.md +89 -1
- package/cjs/date/format.js +2 -1
- package/cjs/date/isFormat.js +17 -12
- package/cjs/deep/get.js +6 -4
- package/cjs/formdata/toObject.js +20 -13
- package/cjs/modules/Scheduler.js +8 -8
- package/cjs/object/merge.js +11 -13
- package/cjs/object/omit.js +69 -17
- package/cjs/object/scramble.js +85 -0
- package/cjs/object/types.js +2 -0
- package/date/isFormat.d.ts +2 -0
- package/esm/date/format.js +2 -1
- package/esm/date/isFormat.js +16 -12
- package/esm/deep/get.js +6 -4
- package/esm/formdata/toObject.js +20 -13
- package/esm/modules/Scheduler.js +8 -8
- package/esm/object/merge.js +11 -13
- package/esm/object/omit.js +69 -17
- package/esm/object/scramble.js +83 -0
- package/esm/object/types.js +1 -0
- package/index.d.ts +32 -16
- package/object/omit.d.ts +9 -10
- package/object/pick.d.ts +1 -3
- package/object/scramble.d.ts +15 -0
- package/object/types.d.ts +12 -0
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -12,6 +12,11 @@ Zero-dependency collection of single-function utilities for common tasks
|
|
|
12
12
|
## Installation
|
|
13
13
|
`npm install @valkyriestudios/utils`
|
|
14
14
|
|
|
15
|
+
## 🧊 TriFrost is powered by utils
|
|
16
|
+
Many of the utilities in this package are optimized and tested as foundational building blocks of [TriFrost](https://www.trifrost.dev) — a high-performance, type-safe framework for building fullstack TypeScript applications.
|
|
17
|
+
|
|
18
|
+
If you're looking to go beyond utilities and build fully modular backends with deep type integration, check out TriFrost.
|
|
19
|
+
|
|
15
20
|
## Available Functions
|
|
16
21
|
### array/is(val:unknown)
|
|
17
22
|
Check if a variable is of type Array
|
|
@@ -1498,7 +1503,7 @@ pick({a: 1, b: 2, c: 3}, ['a','b']); // {a: 1, b: 2}
|
|
|
1498
1503
|
### object/omit(obj:Object={}, keys:Array[string]=[])
|
|
1499
1504
|
Returns an object with the keys provided in the keys array stripped from the provided object.
|
|
1500
1505
|
```typescript
|
|
1501
|
-
import { omit } from "@valkyriestudios/utils/object";
|
|
1506
|
+
import { omit } from "@valkyriestudios/utils/object";
|
|
1502
1507
|
const redacted = omit({
|
|
1503
1508
|
firstName: "Peter",
|
|
1504
1509
|
lastName: "Vermeulen",
|
|
@@ -1519,6 +1524,89 @@ Its type will be
|
|
|
1519
1524
|
*/
|
|
1520
1525
|
```
|
|
1521
1526
|
|
|
1527
|
+
Also works with wildcards (take note, only as **prefix**):
|
|
1528
|
+
```typescript
|
|
1529
|
+
import { omit } from "@valkyriestudios/utils/object";
|
|
1530
|
+
const redacted = omit({
|
|
1531
|
+
firstName: "Peter",
|
|
1532
|
+
lastName: "Vermeulen",
|
|
1533
|
+
age: 34,
|
|
1534
|
+
details: {
|
|
1535
|
+
phone: "...",
|
|
1536
|
+
email: "...",
|
|
1537
|
+
isActive: true,
|
|
1538
|
+
password: "...",
|
|
1539
|
+
},
|
|
1540
|
+
meta: {
|
|
1541
|
+
phone: "...",
|
|
1542
|
+
},
|
|
1543
|
+
}, ["age", "*.phone", "*.email", "*.password"]);
|
|
1544
|
+
/**
|
|
1545
|
+
Redacted here will be:
|
|
1546
|
+
{
|
|
1547
|
+
firstName: "Peter",
|
|
1548
|
+
lastName: "Vermeulen",
|
|
1549
|
+
details: {isActive: true},
|
|
1550
|
+
meta: {}
|
|
1551
|
+
}
|
|
1552
|
+
*/
|
|
1553
|
+
```
|
|
1554
|
+
|
|
1555
|
+
### object/scramble(obj:Object={}, keys:Array[string]=[], options?:{replacement?:string})
|
|
1556
|
+
Returns an object with the keys provided in the keys array scrambled.
|
|
1557
|
+
```typescript
|
|
1558
|
+
import { scramble } from "@valkyriestudios/utils/object";
|
|
1559
|
+
const redacted = scramble({
|
|
1560
|
+
firstName: "Peter",
|
|
1561
|
+
lastName: "Vermeulen",
|
|
1562
|
+
age: 34,
|
|
1563
|
+
details: {
|
|
1564
|
+
phone: "...",
|
|
1565
|
+
email: "...",
|
|
1566
|
+
isActive: true,
|
|
1567
|
+
password: "...",
|
|
1568
|
+
},
|
|
1569
|
+
}, ["age", "details.phone", "details.email", "details.password"]);
|
|
1570
|
+
/**
|
|
1571
|
+
Redacted here will be:
|
|
1572
|
+
{
|
|
1573
|
+
firstName: "Peter",
|
|
1574
|
+
lastName: "Vermeulen",
|
|
1575
|
+
age: "***",
|
|
1576
|
+
details: {phone: "***", email: "***", isActive: true, password: "***"}
|
|
1577
|
+
}
|
|
1578
|
+
*/
|
|
1579
|
+
```
|
|
1580
|
+
|
|
1581
|
+
Also works with wildcards (take note, only as **prefix**):
|
|
1582
|
+
```typescript
|
|
1583
|
+
import { scramble } from "@valkyriestudios/utils/object";
|
|
1584
|
+
const redacted = scramble({
|
|
1585
|
+
firstName: "Peter",
|
|
1586
|
+
lastName: "Vermeulen",
|
|
1587
|
+
age: 34,
|
|
1588
|
+
details: {
|
|
1589
|
+
phone: "...",
|
|
1590
|
+
email: "...",
|
|
1591
|
+
isActive: true,
|
|
1592
|
+
password: "...",
|
|
1593
|
+
},
|
|
1594
|
+
meta: {
|
|
1595
|
+
phone: "...",
|
|
1596
|
+
},
|
|
1597
|
+
}, ["age", "*.phone", "*.email", "*.password"]);
|
|
1598
|
+
/**
|
|
1599
|
+
Redacted here will be:
|
|
1600
|
+
{
|
|
1601
|
+
firstName: "Peter",
|
|
1602
|
+
lastName: "Vermeulen",
|
|
1603
|
+
age: "***",
|
|
1604
|
+
details: {phone: "***", email: "***", isActive: true, password: "***"},
|
|
1605
|
+
meta: {phone: "***"}
|
|
1606
|
+
}
|
|
1607
|
+
*/
|
|
1608
|
+
```
|
|
1609
|
+
|
|
1522
1610
|
### object/merge(target:Object={},obj:Object|Object[]={}, opts?:{union?:boolean})
|
|
1523
1611
|
Merges two objects together, with the preference over the second object.
|
|
1524
1612
|
```typescript
|
package/cjs/date/format.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.format = format;
|
|
7
7
|
exports.default = format;
|
|
8
8
|
const convertToDate_1 = require("./convertToDate");
|
|
9
|
+
const isFormat_1 = require("./isFormat");
|
|
9
10
|
const LRU_1 = __importDefault(require("../caching/LRU"));
|
|
10
11
|
const WEEK_STARTS = {
|
|
11
12
|
mon: 'mon',
|
|
@@ -45,7 +46,7 @@ function toZone(d, zone) {
|
|
|
45
46
|
const month = d.getUTCMonth();
|
|
46
47
|
const day = d.getUTCDate();
|
|
47
48
|
const time = d.getTime();
|
|
48
|
-
const daysInMonths =
|
|
49
|
+
const daysInMonths = (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0) ? isFormat_1.MONTHS_LEAP : isFormat_1.MONTHS;
|
|
49
50
|
let doy = day;
|
|
50
51
|
for (let i = 0; i <= month; i++)
|
|
51
52
|
doy += daysInMonths[i];
|
package/cjs/date/isFormat.js
CHANGED
|
@@ -3,25 +3,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MONTHS = exports.MONTHS_LEAP = void 0;
|
|
6
7
|
exports.isDateFormat = isDateFormat;
|
|
7
8
|
exports.default = isDateFormat;
|
|
8
9
|
const LRU_1 = __importDefault(require("../caching/LRU"));
|
|
9
10
|
const SPECIAL_CHARS = /[.*+?^${}()|[\]\\]/g;
|
|
10
11
|
const TOKENS = [
|
|
11
12
|
['YYYY', /\d{4}/.source, (raw, context) => {
|
|
12
|
-
context.year =
|
|
13
|
+
context.year = raw | 0;
|
|
13
14
|
return context.year > 0;
|
|
14
15
|
}],
|
|
15
16
|
['MM', /(?:0[1-9]|1[0-2])/.source, (raw, context) => {
|
|
16
|
-
context.month =
|
|
17
|
+
context.month = raw | 0;
|
|
17
18
|
return context.month >= 1 && context.month <= 12;
|
|
18
19
|
}],
|
|
19
20
|
['DD', /(?:0[1-9]|[12][0-9]|3[01])/.source, (raw, context) => {
|
|
20
|
-
context.day =
|
|
21
|
+
context.day = raw | 0;
|
|
21
22
|
return context.day >= 1 && context.day <= 31;
|
|
22
23
|
}],
|
|
23
24
|
['HH', /(?:[01][0-9]|2[0-3])/.source, (raw, context) => {
|
|
24
|
-
context.hour =
|
|
25
|
+
context.hour = raw | 0;
|
|
25
26
|
return context.hour >= 0 && context.hour <= 23;
|
|
26
27
|
}],
|
|
27
28
|
['mm', /[0-5][0-9]/.source, () => true],
|
|
@@ -39,10 +40,10 @@ const TOKENS = [
|
|
|
39
40
|
['Z', /Z|[+-](?:0[0-9]|1[0-4]):[0-5][0-9]/.source, raw => {
|
|
40
41
|
if (raw === 'Z')
|
|
41
42
|
return true;
|
|
42
|
-
let hour =
|
|
43
|
+
let hour = (raw[1] + raw[2]) | 0;
|
|
43
44
|
if (raw[0] === '-')
|
|
44
45
|
hour = -hour;
|
|
45
|
-
const minutes =
|
|
46
|
+
const minutes = (raw[4] + raw[5]) | 0;
|
|
46
47
|
if (hour === 14 || hour === -12)
|
|
47
48
|
return minutes === 0;
|
|
48
49
|
return hour >= -11 && hour < 14 && [0, 15, 30, 45].indexOf(minutes) >= 0;
|
|
@@ -52,6 +53,13 @@ const SPEC_ALIASES = {
|
|
|
52
53
|
ISO: 'YYYY-MM-DDTHH:mm:ss{.SSS}Z',
|
|
53
54
|
};
|
|
54
55
|
const spec_pat_cache = new LRU_1.default({ max_size: 100 });
|
|
56
|
+
exports.MONTHS_LEAP = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
57
|
+
exports.MONTHS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
58
|
+
function isValidDay(year, month, day) {
|
|
59
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)
|
|
60
|
+
? day <= exports.MONTHS_LEAP[month - 1]
|
|
61
|
+
: day <= exports.MONTHS[month - 1];
|
|
62
|
+
}
|
|
55
63
|
function compileSpec(spec, is_chunk = false) {
|
|
56
64
|
let cached = spec_pat_cache.get(spec);
|
|
57
65
|
if (cached !== undefined)
|
|
@@ -90,7 +98,7 @@ function compileSpec(spec, is_chunk = false) {
|
|
|
90
98
|
}
|
|
91
99
|
}
|
|
92
100
|
}
|
|
93
|
-
cached = { rgx: is_chunk ? RegExp(pat) : RegExp('^' + pat + '$'), tokens };
|
|
101
|
+
cached = { rgx: is_chunk ? new RegExp(pat) : new RegExp('^' + pat + '$'), tokens };
|
|
94
102
|
spec_pat_cache.set(spec, cached);
|
|
95
103
|
return cached;
|
|
96
104
|
}
|
|
@@ -113,11 +121,8 @@ function isDateFormat(input, spec) {
|
|
|
113
121
|
return false;
|
|
114
122
|
}
|
|
115
123
|
const { is12, day, month, year } = context;
|
|
116
|
-
if (day && month)
|
|
117
|
-
|
|
118
|
-
if (date.getDate() !== day || date.getMonth() !== month - 1)
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
124
|
+
if (day && month && !isValidDay(year || 2024, month, day))
|
|
125
|
+
return false;
|
|
121
126
|
if (is12 && 'hour' in context && context.hour > 11)
|
|
122
127
|
return false;
|
|
123
128
|
return true;
|
package/cjs/deep/get.js
CHANGED
|
@@ -21,8 +21,9 @@ function deepGet(obj, path, get_parent = false) {
|
|
|
21
21
|
if (!key)
|
|
22
22
|
break;
|
|
23
23
|
if (Array.isArray(node)) {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
let ix = Number(key);
|
|
25
|
+
if (!isNaN(ix)) {
|
|
26
|
+
ix = ix | 0;
|
|
26
27
|
if (ix < 0 || ix > node.length - 1)
|
|
27
28
|
return undefined;
|
|
28
29
|
node = node[ix];
|
|
@@ -53,8 +54,9 @@ function deepGet(obj, path, get_parent = false) {
|
|
|
53
54
|
}
|
|
54
55
|
if (key) {
|
|
55
56
|
if (Array.isArray(node)) {
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
let ix = Number(key);
|
|
58
|
+
if (!isNaN(ix)) {
|
|
59
|
+
ix = ix | 0;
|
|
58
60
|
if (ix < 0 || ix > node.length - 1)
|
|
59
61
|
return undefined;
|
|
60
62
|
node = node[ix];
|
package/cjs/formdata/toObject.js
CHANGED
|
@@ -19,7 +19,7 @@ function assign(acc, rawkey, value, single) {
|
|
|
19
19
|
if (i < (keys_len - 1)) {
|
|
20
20
|
const n_key = Array.isArray(cursor) ? Number(key) : key;
|
|
21
21
|
if (!cursor[n_key])
|
|
22
|
-
cursor[n_key] = Number
|
|
22
|
+
cursor[n_key] = isNaN(Number(keys[i + 1])) ? {} : [];
|
|
23
23
|
cursor = cursor[n_key];
|
|
24
24
|
}
|
|
25
25
|
else if (!(key in cursor) || (single && single.has(key))) {
|
|
@@ -50,12 +50,16 @@ function toObject(form, config) {
|
|
|
50
50
|
const nNumber = config?.normalize_number !== false;
|
|
51
51
|
const acc = {};
|
|
52
52
|
if (set === null) {
|
|
53
|
-
|
|
53
|
+
for (const [key, value] of form) {
|
|
54
|
+
assign(acc, key, value, single);
|
|
55
|
+
}
|
|
56
|
+
return acc;
|
|
54
57
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
for (const [key, value] of form) {
|
|
59
|
+
if (set_guard && set.has(key)) {
|
|
60
|
+
assign(acc, key, value, single);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
59
63
|
switch (value) {
|
|
60
64
|
case 'true':
|
|
61
65
|
case 'TRUE':
|
|
@@ -73,20 +77,23 @@ function toObject(form, config) {
|
|
|
73
77
|
assign(acc, key, nNull ? null : value, single);
|
|
74
78
|
break;
|
|
75
79
|
default: {
|
|
76
|
-
if (typeof value === 'string' && value
|
|
80
|
+
if (typeof value === 'string' && value) {
|
|
77
81
|
if (nNumber) {
|
|
78
82
|
const nVal = Number(value);
|
|
79
|
-
if (!isNaN(nVal))
|
|
80
|
-
|
|
83
|
+
if (!isNaN(nVal)) {
|
|
84
|
+
assign(acc, key, nVal, single);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (nDate && (0, isFormat_1.isDateFormat)(value, 'ISO')) {
|
|
89
|
+
assign(acc, key, new Date(value), single);
|
|
90
|
+
continue;
|
|
81
91
|
}
|
|
82
|
-
if (nDate &&
|
|
83
|
-
(0, isFormat_1.isDateFormat)(value, 'ISO'))
|
|
84
|
-
return assign(acc, key, new Date(value), single);
|
|
85
92
|
}
|
|
86
93
|
assign(acc, key, value, single);
|
|
87
94
|
}
|
|
88
95
|
}
|
|
89
|
-
}
|
|
96
|
+
}
|
|
90
97
|
}
|
|
91
98
|
return acc;
|
|
92
99
|
}
|
package/cjs/modules/Scheduler.js
CHANGED
|
@@ -36,7 +36,7 @@ function convertPart(part, min, max) {
|
|
|
36
36
|
const set = new Set();
|
|
37
37
|
if (part.indexOf('/') > -1) {
|
|
38
38
|
const [base, raw_step] = part.split('/', 2);
|
|
39
|
-
const step =
|
|
39
|
+
const step = raw_step | 0;
|
|
40
40
|
let start;
|
|
41
41
|
let end = max;
|
|
42
42
|
if (base === '*') {
|
|
@@ -44,29 +44,29 @@ function convertPart(part, min, max) {
|
|
|
44
44
|
}
|
|
45
45
|
else if (base.indexOf('-') > -1) {
|
|
46
46
|
const chunks = base.split('-', 2);
|
|
47
|
-
start =
|
|
48
|
-
end =
|
|
47
|
+
start = chunks[0] | 0;
|
|
48
|
+
end = chunks[1] | 0;
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
|
-
start =
|
|
51
|
+
start = base | 0;
|
|
52
52
|
}
|
|
53
53
|
for (let i = start; i <= end; i += step)
|
|
54
54
|
set.add(i);
|
|
55
55
|
}
|
|
56
56
|
else if (part.indexOf('-') > -1) {
|
|
57
57
|
const chunks = part.split('-', 2);
|
|
58
|
-
const start =
|
|
59
|
-
const end =
|
|
58
|
+
const start = chunks[0] | 0;
|
|
59
|
+
const end = chunks[1] | 0;
|
|
60
60
|
for (let i = start; i <= end; i++)
|
|
61
61
|
set.add(i);
|
|
62
62
|
}
|
|
63
63
|
else if (part.indexOf(',') > -1) {
|
|
64
64
|
const chunks = part.split(',');
|
|
65
65
|
for (let i = 0; i < chunks.length; i++)
|
|
66
|
-
set.add(
|
|
66
|
+
set.add(chunks[i] | 0);
|
|
67
67
|
}
|
|
68
68
|
else {
|
|
69
|
-
set.add(
|
|
69
|
+
set.add(part | 0);
|
|
70
70
|
}
|
|
71
71
|
return set;
|
|
72
72
|
}
|
package/cjs/object/merge.js
CHANGED
|
@@ -2,33 +2,31 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.merge = merge;
|
|
4
4
|
exports.default = merge;
|
|
5
|
-
const PROTO_OBJ = '[object Object]';
|
|
6
5
|
function innerMerge(target, source, UNION) {
|
|
7
6
|
const origin = UNION ? source : target;
|
|
8
7
|
for (const key in origin) {
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
Object.prototype.toString.call(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
target[key] = s_key !== undefined ? s_key : t_key;
|
|
8
|
+
const t_val = target[key];
|
|
9
|
+
const s_val = source[key];
|
|
10
|
+
if (s_val !== undefined && t_val !== s_val) {
|
|
11
|
+
target[key] = Object.prototype.toString.call(t_val) === '[object Object]' &&
|
|
12
|
+
Object.prototype.toString.call(s_val) === '[object Object]'
|
|
13
|
+
? innerMerge(t_val, s_val, UNION)
|
|
14
|
+
: s_val;
|
|
17
15
|
}
|
|
18
16
|
}
|
|
19
17
|
return target;
|
|
20
18
|
}
|
|
21
19
|
function merge(target, source, opts = {}) {
|
|
22
|
-
if (Object.prototype.toString.call(target) !==
|
|
20
|
+
if (Object.prototype.toString.call(target) !== '[object Object]')
|
|
23
21
|
throw new Error('object/merge: Please ensure valid target/source is passed');
|
|
24
22
|
const union = opts?.union === true;
|
|
25
23
|
const sources = Array.isArray(source) ? source : [source];
|
|
26
24
|
let acc = { ...target };
|
|
27
25
|
for (let i = 0; i < sources.length; i++) {
|
|
28
26
|
const el = sources[i];
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
if (el &&
|
|
28
|
+
Object.prototype.toString.call(el) === '[object Object]')
|
|
29
|
+
acc = innerMerge(acc, el, union);
|
|
32
30
|
}
|
|
33
31
|
return acc;
|
|
34
32
|
}
|
package/cjs/object/omit.js
CHANGED
|
@@ -2,32 +2,84 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.omit = omit;
|
|
4
4
|
exports.default = omit;
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
5
|
+
function wildcardProp(target, source, prop) {
|
|
6
|
+
if (Array.isArray(target)) {
|
|
7
|
+
for (let i = 0; i < target.length; i++) {
|
|
8
|
+
const t = target[i];
|
|
9
|
+
const s = source[i];
|
|
10
|
+
if (typeof t === 'object' && t !== null && typeof s === 'object' && s !== null) {
|
|
11
|
+
if (t === s)
|
|
12
|
+
target[i] = { ...t };
|
|
13
|
+
wildcardProp(target[i], s, prop);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
else if (Object.prototype.toString.call(target) === '[object Object]') {
|
|
18
|
+
for (const key in target) {
|
|
19
|
+
if (key === prop && key in source) {
|
|
20
|
+
delete target[key];
|
|
15
21
|
}
|
|
16
22
|
else {
|
|
17
|
-
|
|
23
|
+
const val = target[key];
|
|
24
|
+
const s_val = source?.[key];
|
|
25
|
+
if (typeof val === 'object' && typeof s_val === 'object' && val !== null && s_val !== null) {
|
|
26
|
+
if (val === s_val) {
|
|
27
|
+
target[key] = Array.isArray(val) ? [...val] : { ...val };
|
|
28
|
+
}
|
|
29
|
+
wildcardProp(target[key], s_val, prop);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function standardProp(target, source, path) {
|
|
36
|
+
const last = path.length - 1;
|
|
37
|
+
for (let i = 0; i < last; i++) {
|
|
38
|
+
const key = path[i];
|
|
39
|
+
const val = target[key];
|
|
40
|
+
const src_val = source?.[key];
|
|
41
|
+
if (Array.isArray(val)) {
|
|
42
|
+
target[key] = val.map((item, idx) => {
|
|
43
|
+
const src_item = src_val[idx];
|
|
44
|
+
if (Object.prototype.toString.call(item) === '[object Object]') {
|
|
45
|
+
const clone = { ...item };
|
|
46
|
+
standardProp(clone, src_item, path.slice(i + 1));
|
|
47
|
+
return clone;
|
|
48
|
+
}
|
|
49
|
+
return item;
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (Object.prototype.toString.call(val) === '[object Object]') {
|
|
54
|
+
if (val === src_val) {
|
|
55
|
+
target[key] = { ...val };
|
|
18
56
|
}
|
|
57
|
+
target = target[key];
|
|
58
|
+
source = src_val;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
return;
|
|
19
62
|
}
|
|
20
63
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
result[root] !== null)
|
|
24
|
-
result[root] = innerOmit(result[root], groups[root]);
|
|
64
|
+
if (target && typeof target === 'object' && path[last] in source) {
|
|
65
|
+
delete target[path[last]];
|
|
25
66
|
}
|
|
26
|
-
return result;
|
|
27
67
|
}
|
|
28
68
|
function omit(obj, keys) {
|
|
29
69
|
if (Object.prototype.toString.call(obj) !== '[object Object]' ||
|
|
30
70
|
!Array.isArray(keys))
|
|
31
71
|
throw new TypeError('Please pass an object to omit from and a keys array');
|
|
32
|
-
|
|
72
|
+
const result = { ...obj };
|
|
73
|
+
for (let i = 0; i < keys.length; i++) {
|
|
74
|
+
const key = keys[i];
|
|
75
|
+
if (typeof key === 'string') {
|
|
76
|
+
if (key.length > 2 && key[0] === '*' && key[1] === '.') {
|
|
77
|
+
wildcardProp(result, obj, key.slice(2));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
standardProp(result, obj, key.split('.'));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
33
85
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function wildcardProp(target, source, prop, repl) {
|
|
4
|
+
if (Array.isArray(target)) {
|
|
5
|
+
for (let i = 0; i < target.length; i++) {
|
|
6
|
+
const t = target[i];
|
|
7
|
+
const s = source[i];
|
|
8
|
+
if (typeof t === 'object' && t !== null && typeof s === 'object' && s !== null) {
|
|
9
|
+
if (t === s)
|
|
10
|
+
target[i] = { ...t };
|
|
11
|
+
wildcardProp(target[i], s, prop, repl);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
else if (Object.prototype.toString.call(target) === '[object Object]') {
|
|
16
|
+
for (const key in target) {
|
|
17
|
+
if (key === prop && key in source) {
|
|
18
|
+
target[key] = repl;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
const val = target[key];
|
|
22
|
+
const s_val = source?.[key];
|
|
23
|
+
if (typeof val === 'object' && typeof s_val === 'object' && val !== null && s_val !== null) {
|
|
24
|
+
if (val === s_val) {
|
|
25
|
+
target[key] = Array.isArray(val) ? [...val] : { ...val };
|
|
26
|
+
}
|
|
27
|
+
wildcardProp(target[key], s_val, prop, repl);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function standardProp(target, source, path, repl) {
|
|
34
|
+
const last = path.length - 1;
|
|
35
|
+
for (let i = 0; i < last; i++) {
|
|
36
|
+
const key = path[i];
|
|
37
|
+
const val = target[key];
|
|
38
|
+
const src_val = source?.[key];
|
|
39
|
+
if (Array.isArray(val)) {
|
|
40
|
+
target[key] = val.map((item, idx) => {
|
|
41
|
+
const src_item = src_val[idx];
|
|
42
|
+
if (Object.prototype.toString.call(item) === '[object Object]') {
|
|
43
|
+
const clone = { ...item };
|
|
44
|
+
standardProp(clone, src_item, path.slice(i + 1), repl);
|
|
45
|
+
return clone;
|
|
46
|
+
}
|
|
47
|
+
return item;
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
else if (Object.prototype.toString.call(val) === '[object Object]') {
|
|
52
|
+
if (val === src_val) {
|
|
53
|
+
target[key] = { ...val };
|
|
54
|
+
}
|
|
55
|
+
target = target[key];
|
|
56
|
+
source = src_val;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (target && typeof target === 'object' && path[last] in source) {
|
|
63
|
+
target[path[last]] = repl;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function scramble(obj, keys, options) {
|
|
67
|
+
if (Object.prototype.toString.call(obj) !== '[object Object]' ||
|
|
68
|
+
!Array.isArray(keys))
|
|
69
|
+
throw new TypeError('Please pass an object to scramble and a keys array');
|
|
70
|
+
const repl = typeof options?.replacement === 'string' ? options.replacement : '***';
|
|
71
|
+
const result = { ...obj };
|
|
72
|
+
for (let i = 0; i < keys.length; i++) {
|
|
73
|
+
const key = keys[i];
|
|
74
|
+
if (typeof key === 'string') {
|
|
75
|
+
if (key.length > 2 && key[0] === '*' && key[1] === '.') {
|
|
76
|
+
wildcardProp(result, obj, key.slice(2), repl);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
standardProp(result, obj, key.split('.'), repl);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
exports.default = scramble;
|
package/date/isFormat.d.ts
CHANGED
package/esm/date/format.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { convertToDate } from './convertToDate';
|
|
2
|
+
import { MONTHS, MONTHS_LEAP } from './isFormat';
|
|
2
3
|
import LRU from '../caching/LRU';
|
|
3
4
|
const WEEK_STARTS = {
|
|
4
5
|
mon: 'mon',
|
|
@@ -38,7 +39,7 @@ function toZone(d, zone) {
|
|
|
38
39
|
const month = d.getUTCMonth();
|
|
39
40
|
const day = d.getUTCDate();
|
|
40
41
|
const time = d.getTime();
|
|
41
|
-
const daysInMonths =
|
|
42
|
+
const daysInMonths = (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0) ? MONTHS_LEAP : MONTHS;
|
|
42
43
|
let doy = day;
|
|
43
44
|
for (let i = 0; i <= month; i++)
|
|
44
45
|
doy += daysInMonths[i];
|
package/esm/date/isFormat.js
CHANGED
|
@@ -2,19 +2,19 @@ import LRU from '../caching/LRU';
|
|
|
2
2
|
const SPECIAL_CHARS = /[.*+?^${}()|[\]\\]/g;
|
|
3
3
|
const TOKENS = [
|
|
4
4
|
['YYYY', /\d{4}/.source, (raw, context) => {
|
|
5
|
-
context.year =
|
|
5
|
+
context.year = raw | 0;
|
|
6
6
|
return context.year > 0;
|
|
7
7
|
}],
|
|
8
8
|
['MM', /(?:0[1-9]|1[0-2])/.source, (raw, context) => {
|
|
9
|
-
context.month =
|
|
9
|
+
context.month = raw | 0;
|
|
10
10
|
return context.month >= 1 && context.month <= 12;
|
|
11
11
|
}],
|
|
12
12
|
['DD', /(?:0[1-9]|[12][0-9]|3[01])/.source, (raw, context) => {
|
|
13
|
-
context.day =
|
|
13
|
+
context.day = raw | 0;
|
|
14
14
|
return context.day >= 1 && context.day <= 31;
|
|
15
15
|
}],
|
|
16
16
|
['HH', /(?:[01][0-9]|2[0-3])/.source, (raw, context) => {
|
|
17
|
-
context.hour =
|
|
17
|
+
context.hour = raw | 0;
|
|
18
18
|
return context.hour >= 0 && context.hour <= 23;
|
|
19
19
|
}],
|
|
20
20
|
['mm', /[0-5][0-9]/.source, () => true],
|
|
@@ -32,10 +32,10 @@ const TOKENS = [
|
|
|
32
32
|
['Z', /Z|[+-](?:0[0-9]|1[0-4]):[0-5][0-9]/.source, raw => {
|
|
33
33
|
if (raw === 'Z')
|
|
34
34
|
return true;
|
|
35
|
-
let hour =
|
|
35
|
+
let hour = (raw[1] + raw[2]) | 0;
|
|
36
36
|
if (raw[0] === '-')
|
|
37
37
|
hour = -hour;
|
|
38
|
-
const minutes =
|
|
38
|
+
const minutes = (raw[4] + raw[5]) | 0;
|
|
39
39
|
if (hour === 14 || hour === -12)
|
|
40
40
|
return minutes === 0;
|
|
41
41
|
return hour >= -11 && hour < 14 && [0, 15, 30, 45].indexOf(minutes) >= 0;
|
|
@@ -45,6 +45,13 @@ const SPEC_ALIASES = {
|
|
|
45
45
|
ISO: 'YYYY-MM-DDTHH:mm:ss{.SSS}Z',
|
|
46
46
|
};
|
|
47
47
|
const spec_pat_cache = new LRU({ max_size: 100 });
|
|
48
|
+
export const MONTHS_LEAP = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
49
|
+
export const MONTHS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
50
|
+
function isValidDay(year, month, day) {
|
|
51
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)
|
|
52
|
+
? day <= MONTHS_LEAP[month - 1]
|
|
53
|
+
: day <= MONTHS[month - 1];
|
|
54
|
+
}
|
|
48
55
|
function compileSpec(spec, is_chunk = false) {
|
|
49
56
|
let cached = spec_pat_cache.get(spec);
|
|
50
57
|
if (cached !== undefined)
|
|
@@ -83,7 +90,7 @@ function compileSpec(spec, is_chunk = false) {
|
|
|
83
90
|
}
|
|
84
91
|
}
|
|
85
92
|
}
|
|
86
|
-
cached = { rgx: is_chunk ? RegExp(pat) : RegExp('^' + pat + '$'), tokens };
|
|
93
|
+
cached = { rgx: is_chunk ? new RegExp(pat) : new RegExp('^' + pat + '$'), tokens };
|
|
87
94
|
spec_pat_cache.set(spec, cached);
|
|
88
95
|
return cached;
|
|
89
96
|
}
|
|
@@ -106,11 +113,8 @@ function isDateFormat(input, spec) {
|
|
|
106
113
|
return false;
|
|
107
114
|
}
|
|
108
115
|
const { is12, day, month, year } = context;
|
|
109
|
-
if (day && month)
|
|
110
|
-
|
|
111
|
-
if (date.getDate() !== day || date.getMonth() !== month - 1)
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
116
|
+
if (day && month && !isValidDay(year || 2024, month, day))
|
|
117
|
+
return false;
|
|
114
118
|
if (is12 && 'hour' in context && context.hour > 11)
|
|
115
119
|
return false;
|
|
116
120
|
return true;
|
package/esm/deep/get.js
CHANGED
|
@@ -17,8 +17,9 @@ function deepGet(obj, path, get_parent = false) {
|
|
|
17
17
|
if (!key)
|
|
18
18
|
break;
|
|
19
19
|
if (Array.isArray(node)) {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
let ix = Number(key);
|
|
21
|
+
if (!isNaN(ix)) {
|
|
22
|
+
ix = ix | 0;
|
|
22
23
|
if (ix < 0 || ix > node.length - 1)
|
|
23
24
|
return undefined;
|
|
24
25
|
node = node[ix];
|
|
@@ -49,8 +50,9 @@ function deepGet(obj, path, get_parent = false) {
|
|
|
49
50
|
}
|
|
50
51
|
if (key) {
|
|
51
52
|
if (Array.isArray(node)) {
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
let ix = Number(key);
|
|
54
|
+
if (!isNaN(ix)) {
|
|
55
|
+
ix = ix | 0;
|
|
54
56
|
if (ix < 0 || ix > node.length - 1)
|
|
55
57
|
return undefined;
|
|
56
58
|
node = node[ix];
|
package/esm/formdata/toObject.js
CHANGED
|
@@ -15,7 +15,7 @@ function assign(acc, rawkey, value, single) {
|
|
|
15
15
|
if (i < (keys_len - 1)) {
|
|
16
16
|
const n_key = Array.isArray(cursor) ? Number(key) : key;
|
|
17
17
|
if (!cursor[n_key])
|
|
18
|
-
cursor[n_key] = Number
|
|
18
|
+
cursor[n_key] = isNaN(Number(keys[i + 1])) ? {} : [];
|
|
19
19
|
cursor = cursor[n_key];
|
|
20
20
|
}
|
|
21
21
|
else if (!(key in cursor) || (single && single.has(key))) {
|
|
@@ -46,12 +46,16 @@ function toObject(form, config) {
|
|
|
46
46
|
const nNumber = config?.normalize_number !== false;
|
|
47
47
|
const acc = {};
|
|
48
48
|
if (set === null) {
|
|
49
|
-
|
|
49
|
+
for (const [key, value] of form) {
|
|
50
|
+
assign(acc, key, value, single);
|
|
51
|
+
}
|
|
52
|
+
return acc;
|
|
50
53
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
for (const [key, value] of form) {
|
|
55
|
+
if (set_guard && set.has(key)) {
|
|
56
|
+
assign(acc, key, value, single);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
55
59
|
switch (value) {
|
|
56
60
|
case 'true':
|
|
57
61
|
case 'TRUE':
|
|
@@ -69,20 +73,23 @@ function toObject(form, config) {
|
|
|
69
73
|
assign(acc, key, nNull ? null : value, single);
|
|
70
74
|
break;
|
|
71
75
|
default: {
|
|
72
|
-
if (typeof value === 'string' && value
|
|
76
|
+
if (typeof value === 'string' && value) {
|
|
73
77
|
if (nNumber) {
|
|
74
78
|
const nVal = Number(value);
|
|
75
|
-
if (!isNaN(nVal))
|
|
76
|
-
|
|
79
|
+
if (!isNaN(nVal)) {
|
|
80
|
+
assign(acc, key, nVal, single);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (nDate && isDateFormat(value, 'ISO')) {
|
|
85
|
+
assign(acc, key, new Date(value), single);
|
|
86
|
+
continue;
|
|
77
87
|
}
|
|
78
|
-
if (nDate &&
|
|
79
|
-
isDateFormat(value, 'ISO'))
|
|
80
|
-
return assign(acc, key, new Date(value), single);
|
|
81
88
|
}
|
|
82
89
|
assign(acc, key, value, single);
|
|
83
90
|
}
|
|
84
91
|
}
|
|
85
|
-
}
|
|
92
|
+
}
|
|
86
93
|
}
|
|
87
94
|
return acc;
|
|
88
95
|
}
|
package/esm/modules/Scheduler.js
CHANGED
|
@@ -33,7 +33,7 @@ function convertPart(part, min, max) {
|
|
|
33
33
|
const set = new Set();
|
|
34
34
|
if (part.indexOf('/') > -1) {
|
|
35
35
|
const [base, raw_step] = part.split('/', 2);
|
|
36
|
-
const step =
|
|
36
|
+
const step = raw_step | 0;
|
|
37
37
|
let start;
|
|
38
38
|
let end = max;
|
|
39
39
|
if (base === '*') {
|
|
@@ -41,29 +41,29 @@ function convertPart(part, min, max) {
|
|
|
41
41
|
}
|
|
42
42
|
else if (base.indexOf('-') > -1) {
|
|
43
43
|
const chunks = base.split('-', 2);
|
|
44
|
-
start =
|
|
45
|
-
end =
|
|
44
|
+
start = chunks[0] | 0;
|
|
45
|
+
end = chunks[1] | 0;
|
|
46
46
|
}
|
|
47
47
|
else {
|
|
48
|
-
start =
|
|
48
|
+
start = base | 0;
|
|
49
49
|
}
|
|
50
50
|
for (let i = start; i <= end; i += step)
|
|
51
51
|
set.add(i);
|
|
52
52
|
}
|
|
53
53
|
else if (part.indexOf('-') > -1) {
|
|
54
54
|
const chunks = part.split('-', 2);
|
|
55
|
-
const start =
|
|
56
|
-
const end =
|
|
55
|
+
const start = chunks[0] | 0;
|
|
56
|
+
const end = chunks[1] | 0;
|
|
57
57
|
for (let i = start; i <= end; i++)
|
|
58
58
|
set.add(i);
|
|
59
59
|
}
|
|
60
60
|
else if (part.indexOf(',') > -1) {
|
|
61
61
|
const chunks = part.split(',');
|
|
62
62
|
for (let i = 0; i < chunks.length; i++)
|
|
63
|
-
set.add(
|
|
63
|
+
set.add(chunks[i] | 0);
|
|
64
64
|
}
|
|
65
65
|
else {
|
|
66
|
-
set.add(
|
|
66
|
+
set.add(part | 0);
|
|
67
67
|
}
|
|
68
68
|
return set;
|
|
69
69
|
}
|
package/esm/object/merge.js
CHANGED
|
@@ -1,30 +1,28 @@
|
|
|
1
|
-
const PROTO_OBJ = '[object Object]';
|
|
2
1
|
function innerMerge(target, source, UNION) {
|
|
3
2
|
const origin = UNION ? source : target;
|
|
4
3
|
for (const key in origin) {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
if (
|
|
8
|
-
Object.prototype.toString.call(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
target[key] = s_key !== undefined ? s_key : t_key;
|
|
4
|
+
const t_val = target[key];
|
|
5
|
+
const s_val = source[key];
|
|
6
|
+
if (s_val !== undefined && t_val !== s_val) {
|
|
7
|
+
target[key] = Object.prototype.toString.call(t_val) === '[object Object]' &&
|
|
8
|
+
Object.prototype.toString.call(s_val) === '[object Object]'
|
|
9
|
+
? innerMerge(t_val, s_val, UNION)
|
|
10
|
+
: s_val;
|
|
13
11
|
}
|
|
14
12
|
}
|
|
15
13
|
return target;
|
|
16
14
|
}
|
|
17
15
|
function merge(target, source, opts = {}) {
|
|
18
|
-
if (Object.prototype.toString.call(target) !==
|
|
16
|
+
if (Object.prototype.toString.call(target) !== '[object Object]')
|
|
19
17
|
throw new Error('object/merge: Please ensure valid target/source is passed');
|
|
20
18
|
const union = opts?.union === true;
|
|
21
19
|
const sources = Array.isArray(source) ? source : [source];
|
|
22
20
|
let acc = { ...target };
|
|
23
21
|
for (let i = 0; i < sources.length; i++) {
|
|
24
22
|
const el = sources[i];
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
if (el &&
|
|
24
|
+
Object.prototype.toString.call(el) === '[object Object]')
|
|
25
|
+
acc = innerMerge(acc, el, union);
|
|
28
26
|
}
|
|
29
27
|
return acc;
|
|
30
28
|
}
|
package/esm/object/omit.js
CHANGED
|
@@ -1,30 +1,82 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
function wildcardProp(target, source, prop) {
|
|
2
|
+
if (Array.isArray(target)) {
|
|
3
|
+
for (let i = 0; i < target.length; i++) {
|
|
4
|
+
const t = target[i];
|
|
5
|
+
const s = source[i];
|
|
6
|
+
if (typeof t === 'object' && t !== null && typeof s === 'object' && s !== null) {
|
|
7
|
+
if (t === s)
|
|
8
|
+
target[i] = { ...t };
|
|
9
|
+
wildcardProp(target[i], s, prop);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
else if (Object.prototype.toString.call(target) === '[object Object]') {
|
|
14
|
+
for (const key in target) {
|
|
15
|
+
if (key === prop && key in source) {
|
|
16
|
+
delete target[key];
|
|
11
17
|
}
|
|
12
18
|
else {
|
|
13
|
-
|
|
19
|
+
const val = target[key];
|
|
20
|
+
const s_val = source?.[key];
|
|
21
|
+
if (typeof val === 'object' && typeof s_val === 'object' && val !== null && s_val !== null) {
|
|
22
|
+
if (val === s_val) {
|
|
23
|
+
target[key] = Array.isArray(val) ? [...val] : { ...val };
|
|
24
|
+
}
|
|
25
|
+
wildcardProp(target[key], s_val, prop);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function standardProp(target, source, path) {
|
|
32
|
+
const last = path.length - 1;
|
|
33
|
+
for (let i = 0; i < last; i++) {
|
|
34
|
+
const key = path[i];
|
|
35
|
+
const val = target[key];
|
|
36
|
+
const src_val = source?.[key];
|
|
37
|
+
if (Array.isArray(val)) {
|
|
38
|
+
target[key] = val.map((item, idx) => {
|
|
39
|
+
const src_item = src_val[idx];
|
|
40
|
+
if (Object.prototype.toString.call(item) === '[object Object]') {
|
|
41
|
+
const clone = { ...item };
|
|
42
|
+
standardProp(clone, src_item, path.slice(i + 1));
|
|
43
|
+
return clone;
|
|
44
|
+
}
|
|
45
|
+
return item;
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (Object.prototype.toString.call(val) === '[object Object]') {
|
|
50
|
+
if (val === src_val) {
|
|
51
|
+
target[key] = { ...val };
|
|
14
52
|
}
|
|
53
|
+
target = target[key];
|
|
54
|
+
source = src_val;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
return;
|
|
15
58
|
}
|
|
16
59
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
result[root] !== null)
|
|
20
|
-
result[root] = innerOmit(result[root], groups[root]);
|
|
60
|
+
if (target && typeof target === 'object' && path[last] in source) {
|
|
61
|
+
delete target[path[last]];
|
|
21
62
|
}
|
|
22
|
-
return result;
|
|
23
63
|
}
|
|
24
64
|
function omit(obj, keys) {
|
|
25
65
|
if (Object.prototype.toString.call(obj) !== '[object Object]' ||
|
|
26
66
|
!Array.isArray(keys))
|
|
27
67
|
throw new TypeError('Please pass an object to omit from and a keys array');
|
|
28
|
-
|
|
68
|
+
const result = { ...obj };
|
|
69
|
+
for (let i = 0; i < keys.length; i++) {
|
|
70
|
+
const key = keys[i];
|
|
71
|
+
if (typeof key === 'string') {
|
|
72
|
+
if (key.length > 2 && key[0] === '*' && key[1] === '.') {
|
|
73
|
+
wildcardProp(result, obj, key.slice(2));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
standardProp(result, obj, key.split('.'));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
29
81
|
}
|
|
30
82
|
export { omit, omit as default };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
function wildcardProp(target, source, prop, repl) {
|
|
2
|
+
if (Array.isArray(target)) {
|
|
3
|
+
for (let i = 0; i < target.length; i++) {
|
|
4
|
+
const t = target[i];
|
|
5
|
+
const s = source[i];
|
|
6
|
+
if (typeof t === 'object' && t !== null && typeof s === 'object' && s !== null) {
|
|
7
|
+
if (t === s)
|
|
8
|
+
target[i] = { ...t };
|
|
9
|
+
wildcardProp(target[i], s, prop, repl);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
else if (Object.prototype.toString.call(target) === '[object Object]') {
|
|
14
|
+
for (const key in target) {
|
|
15
|
+
if (key === prop && key in source) {
|
|
16
|
+
target[key] = repl;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
const val = target[key];
|
|
20
|
+
const s_val = source?.[key];
|
|
21
|
+
if (typeof val === 'object' && typeof s_val === 'object' && val !== null && s_val !== null) {
|
|
22
|
+
if (val === s_val) {
|
|
23
|
+
target[key] = Array.isArray(val) ? [...val] : { ...val };
|
|
24
|
+
}
|
|
25
|
+
wildcardProp(target[key], s_val, prop, repl);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function standardProp(target, source, path, repl) {
|
|
32
|
+
const last = path.length - 1;
|
|
33
|
+
for (let i = 0; i < last; i++) {
|
|
34
|
+
const key = path[i];
|
|
35
|
+
const val = target[key];
|
|
36
|
+
const src_val = source?.[key];
|
|
37
|
+
if (Array.isArray(val)) {
|
|
38
|
+
target[key] = val.map((item, idx) => {
|
|
39
|
+
const src_item = src_val[idx];
|
|
40
|
+
if (Object.prototype.toString.call(item) === '[object Object]') {
|
|
41
|
+
const clone = { ...item };
|
|
42
|
+
standardProp(clone, src_item, path.slice(i + 1), repl);
|
|
43
|
+
return clone;
|
|
44
|
+
}
|
|
45
|
+
return item;
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
else if (Object.prototype.toString.call(val) === '[object Object]') {
|
|
50
|
+
if (val === src_val) {
|
|
51
|
+
target[key] = { ...val };
|
|
52
|
+
}
|
|
53
|
+
target = target[key];
|
|
54
|
+
source = src_val;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (target && typeof target === 'object' && path[last] in source) {
|
|
61
|
+
target[path[last]] = repl;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function scramble(obj, keys, options) {
|
|
65
|
+
if (Object.prototype.toString.call(obj) !== '[object Object]' ||
|
|
66
|
+
!Array.isArray(keys))
|
|
67
|
+
throw new TypeError('Please pass an object to scramble and a keys array');
|
|
68
|
+
const repl = typeof options?.replacement === 'string' ? options.replacement : '***';
|
|
69
|
+
const result = { ...obj };
|
|
70
|
+
for (let i = 0; i < keys.length; i++) {
|
|
71
|
+
const key = keys[i];
|
|
72
|
+
if (typeof key === 'string') {
|
|
73
|
+
if (key.length > 2 && key[0] === '*' && key[1] === '.') {
|
|
74
|
+
wildcardProp(result, obj, key.slice(2), repl);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
standardProp(result, obj, key.split('.'), repl);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
export default scramble;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/index.d.ts
CHANGED
|
@@ -205,6 +205,12 @@ declare module "caching/LRU" {
|
|
|
205
205
|
}
|
|
206
206
|
export { LRUCache, LRUCache as default };
|
|
207
207
|
}
|
|
208
|
+
declare module "date/isFormat" {
|
|
209
|
+
export const MONTHS_LEAP: number[];
|
|
210
|
+
export const MONTHS: number[];
|
|
211
|
+
function isDateFormat(input: unknown, spec: string): input is string;
|
|
212
|
+
export { isDateFormat, isDateFormat as default };
|
|
213
|
+
}
|
|
208
214
|
declare module "date/format" {
|
|
209
215
|
const WEEK_STARTS: {
|
|
210
216
|
readonly mon: "mon";
|
|
@@ -262,10 +268,6 @@ declare module "date/toUTC" {
|
|
|
262
268
|
function toUTC(val: Date): Date;
|
|
263
269
|
export { toUTC, toUTC as default };
|
|
264
270
|
}
|
|
265
|
-
declare module "date/isFormat" {
|
|
266
|
-
function isDateFormat(input: unknown, spec: string): input is string;
|
|
267
|
-
export { isDateFormat, isDateFormat as default };
|
|
268
|
-
}
|
|
269
271
|
declare module "date/index" {
|
|
270
272
|
export { addUTC } from "date/addUTC";
|
|
271
273
|
export { convertToDate } from "date/convertToDate";
|
|
@@ -377,13 +379,25 @@ declare module "deep/get" {
|
|
|
377
379
|
function deepGet<T extends ObjectType | ArrayType, P extends string>(obj: T, path: P, get_parent?: boolean): DeepGetResult<T, P> | undefined;
|
|
378
380
|
export { deepGet, deepGet as default };
|
|
379
381
|
}
|
|
382
|
+
declare module "object/types" {
|
|
383
|
+
export type DottedKeys<T> = (T extends Record<string, any> ? {
|
|
384
|
+
[K in keyof T & string]: T[K] extends Record<string, any> ? K | `${K}.${DottedKeys<T[K]>}` : K;
|
|
385
|
+
}[keyof T & string] : string) & string;
|
|
386
|
+
export type DottedKeysWithArray<T> = (T extends Record<string, any> ? {
|
|
387
|
+
[K in keyof T & string]: T[K] extends (infer U)[] ? U extends Record<string, any> ? K | `${K}.${DottedKeysWithArray<U>}` : K : T[K] extends Record<string, any> ? K | `${K}.${DottedKeysWithArray<T[K]>}` : K;
|
|
388
|
+
}[keyof T & string] : string) & string;
|
|
389
|
+
export type ExpandWildcard<T, P extends string> = P extends `*.${infer Key}` ? {
|
|
390
|
+
[K in keyof T]: T[K] extends Record<string, any> ? `${K & string}.${Key}` : never;
|
|
391
|
+
}[keyof T] : P;
|
|
392
|
+
export type ExpandWildcardWithArray<T, P extends string> = P extends `*.${infer Key}` ? {
|
|
393
|
+
[K in keyof T]: T[K] extends (infer U)[] ? U extends Record<string, any> ? `${K & string}.${Key}` : never : T[K] extends Record<string, any> ? `${K & string}.${Key}` : never;
|
|
394
|
+
}[keyof T] : P;
|
|
395
|
+
}
|
|
380
396
|
declare module "object/pick" {
|
|
397
|
+
import { type DottedKeys } from "object/types";
|
|
381
398
|
type ObjectType = {
|
|
382
399
|
[key: string]: any;
|
|
383
400
|
};
|
|
384
|
-
type DottedKeys<T> = (T extends ObjectType ? {
|
|
385
|
-
[K in keyof T & string]: T[K] extends ObjectType ? K | `${K}.${DottedKeys<T[K]>}` : K;
|
|
386
|
-
}[keyof T & string] : string) & string;
|
|
387
401
|
type PickFromObject<T, K extends string> = K extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? T[Key] extends ObjectType ? {
|
|
388
402
|
[P in Key]: PickFromObject<T[Key], Rest>;
|
|
389
403
|
} : object : object : K extends keyof T ? {
|
|
@@ -394,16 +408,11 @@ declare module "object/pick" {
|
|
|
394
408
|
export { pick, pick as default };
|
|
395
409
|
}
|
|
396
410
|
declare module "object/omit" {
|
|
397
|
-
type
|
|
398
|
-
|
|
399
|
-
};
|
|
400
|
-
type DottedKeys<T> = (T extends ObjectType ? {
|
|
401
|
-
[K in keyof T & string]: T[K] extends ObjectType ? K | `${K}.${DottedKeys<T[K]>}` : K;
|
|
402
|
-
}[keyof T & string] : string) & string;
|
|
403
|
-
type OmitFromObject<T, K extends string> = K extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? T[Key] extends ObjectType ? {
|
|
411
|
+
import { type DottedKeysWithArray, type ExpandWildcardWithArray } from "object/types";
|
|
412
|
+
type OmitFromObject<T, K extends string> = T extends (infer U)[] ? OmitFromObject<U, K>[] : T extends Record<string, any> ? K extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? T[Key] extends Record<string, any> | any[] ? {
|
|
404
413
|
[P in keyof T]: P extends Key ? OmitFromObject<T[Key], Rest> : T[P];
|
|
405
|
-
} : T : T : Omit<T, K
|
|
406
|
-
function omit<T extends Record<string, any>, K extends readonly
|
|
414
|
+
} : T : T : Omit<T, K> : T;
|
|
415
|
+
function omit<T extends Record<string, any>, K extends readonly (DottedKeysWithArray<T> | `*.${string}`)[]>(obj: T, keys: K): OmitFromObject<T, ExpandWildcardWithArray<T, K[number]>>;
|
|
407
416
|
export { omit, omit as default };
|
|
408
417
|
}
|
|
409
418
|
declare module "object/index" {
|
|
@@ -775,3 +784,10 @@ declare module "modules/index" {
|
|
|
775
784
|
export { PubSub } from "modules/PubSub";
|
|
776
785
|
export { Scheduler } from "modules/Scheduler";
|
|
777
786
|
}
|
|
787
|
+
declare module "object/scramble" {
|
|
788
|
+
import { type DottedKeysWithArray } from "object/types";
|
|
789
|
+
function scramble<T extends Record<string, any>, K extends readonly (DottedKeysWithArray<T> | `*.${string}`)[]>(obj: T, keys: K, options?: {
|
|
790
|
+
replacement?: string;
|
|
791
|
+
}): T;
|
|
792
|
+
export default scramble;
|
|
793
|
+
}
|
package/object/omit.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
type
|
|
2
|
-
|
|
3
|
-
};
|
|
4
|
-
type DottedKeys<T> = (T extends ObjectType ? {
|
|
5
|
-
[K in keyof T & string]: T[K] extends ObjectType ? K | `${K}.${DottedKeys<T[K]>}` : K;
|
|
6
|
-
}[keyof T & string] : string) & string;
|
|
7
|
-
type OmitFromObject<T, K extends string> = K extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? T[Key] extends ObjectType ? {
|
|
1
|
+
import { type DottedKeysWithArray, type ExpandWildcardWithArray } from './types';
|
|
2
|
+
type OmitFromObject<T, K extends string> = T extends (infer U)[] ? OmitFromObject<U, K>[] : T extends Record<string, any> ? K extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? T[Key] extends Record<string, any> | any[] ? {
|
|
8
3
|
[P in keyof T]: P extends Key ? OmitFromObject<T[Key], Rest> : T[P];
|
|
9
|
-
} : T : T : Omit<T, K
|
|
4
|
+
} : T : T : Omit<T, K> : T;
|
|
10
5
|
/**
|
|
11
|
-
* Returns a new object with the keys omitted
|
|
6
|
+
* Returns a new object with the provided keys omitted
|
|
7
|
+
* Supports:
|
|
8
|
+
* - omitting keys in nested arrays
|
|
9
|
+
* - omitting wildcard patterns: '*.password'
|
|
10
|
+
* - omitting standard keys
|
|
12
11
|
*
|
|
13
12
|
* @param {Record<string, any>} obj - Object to omit from
|
|
14
13
|
* @param {string[]} keys - Array of keys to omit from object
|
|
15
14
|
*/
|
|
16
|
-
declare function omit<T extends Record<string, any>, K extends readonly
|
|
15
|
+
declare function omit<T extends Record<string, any>, K extends readonly (DottedKeysWithArray<T> | `*.${string}`)[]>(obj: T, keys: K): OmitFromObject<T, ExpandWildcardWithArray<T, K[number]>>;
|
|
17
16
|
export { omit, omit as default };
|
package/object/pick.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
+
import { type DottedKeys } from './types';
|
|
1
2
|
type ObjectType = {
|
|
2
3
|
[key: string]: any;
|
|
3
4
|
};
|
|
4
|
-
type DottedKeys<T> = (T extends ObjectType ? {
|
|
5
|
-
[K in keyof T & string]: T[K] extends ObjectType ? K | `${K}.${DottedKeys<T[K]>}` : K;
|
|
6
|
-
}[keyof T & string] : string) & string;
|
|
7
5
|
type PickFromObject<T, K extends string> = K extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? T[Key] extends ObjectType ? {
|
|
8
6
|
[P in Key]: PickFromObject<T[Key], Rest>;
|
|
9
7
|
} : object : object : K extends keyof T ? {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type DottedKeysWithArray } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns a new object with the provided keys obfuscated
|
|
4
|
+
* Supports:
|
|
5
|
+
* - scrambling keys in nested arrays
|
|
6
|
+
* - scrambling wildcard patterns: '*.password'
|
|
7
|
+
* - scrambling standard keys
|
|
8
|
+
*
|
|
9
|
+
* @param {Record<string, any>} obj - Object to omit from
|
|
10
|
+
* @param {string[]} keys - Array of keys to omit from object
|
|
11
|
+
*/
|
|
12
|
+
declare function scramble<T extends Record<string, any>, K extends readonly (DottedKeysWithArray<T> | `*.${string}`)[]>(obj: T, keys: K, options?: {
|
|
13
|
+
replacement?: string;
|
|
14
|
+
}): T;
|
|
15
|
+
export default scramble;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type DottedKeys<T> = (T extends Record<string, any> ? {
|
|
2
|
+
[K in keyof T & string]: T[K] extends Record<string, any> ? K | `${K}.${DottedKeys<T[K]>}` : K;
|
|
3
|
+
}[keyof T & string] : string) & string;
|
|
4
|
+
export type DottedKeysWithArray<T> = (T extends Record<string, any> ? {
|
|
5
|
+
[K in keyof T & string]: T[K] extends (infer U)[] ? U extends Record<string, any> ? K | `${K}.${DottedKeysWithArray<U>}` : K : T[K] extends Record<string, any> ? K | `${K}.${DottedKeysWithArray<T[K]>}` : K;
|
|
6
|
+
}[keyof T & string] : string) & string;
|
|
7
|
+
export type ExpandWildcard<T, P extends string> = P extends `*.${infer Key}` ? {
|
|
8
|
+
[K in keyof T]: T[K] extends Record<string, any> ? `${K & string}.${Key}` : never;
|
|
9
|
+
}[keyof T] : P;
|
|
10
|
+
export type ExpandWildcardWithArray<T, P extends string> = P extends `*.${infer Key}` ? {
|
|
11
|
+
[K in keyof T]: T[K] extends (infer U)[] ? U extends Record<string, any> ? `${K & string}.${Key}` : never : T[K] extends Record<string, any> ? `${K & string}.${Key}` : never;
|
|
12
|
+
}[keyof T] : P;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@valkyriestudios/utils",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.41.0",
|
|
4
4
|
"description": "A collection of single-function utilities for common tasks",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Peter Vermeulen",
|
|
@@ -457,6 +457,11 @@
|
|
|
457
457
|
"import": "./esm/object/pick.js",
|
|
458
458
|
"require": "./cjs/object/pick.js"
|
|
459
459
|
},
|
|
460
|
+
"./object/scramble": {
|
|
461
|
+
"types": "./object/scramble.d.ts",
|
|
462
|
+
"import": "./esm/object/scramble.js",
|
|
463
|
+
"require": "./cjs/object/scramble.js"
|
|
464
|
+
},
|
|
460
465
|
"./regexp": {
|
|
461
466
|
"types": "./regexp/index.d.ts",
|
|
462
467
|
"import": "./esm/regexp/index.js",
|
|
@@ -509,12 +514,12 @@
|
|
|
509
514
|
}
|
|
510
515
|
},
|
|
511
516
|
"devDependencies": {
|
|
512
|
-
"@types/node": "^22.15.
|
|
513
|
-
"@vitest/coverage-v8": "^3.
|
|
517
|
+
"@types/node": "^22.15.30",
|
|
518
|
+
"@vitest/coverage-v8": "^3.2.2",
|
|
514
519
|
"esbuild-register": "^3.6.0",
|
|
515
|
-
"eslint": "^9.
|
|
520
|
+
"eslint": "^9.28.0",
|
|
516
521
|
"typescript": "^5.8.3",
|
|
517
|
-
"typescript-eslint": "^8.33.
|
|
518
|
-
"vitest": "^3.
|
|
522
|
+
"typescript-eslint": "^8.33.1",
|
|
523
|
+
"vitest": "^3.2.2"
|
|
519
524
|
}
|
|
520
525
|
}
|