@valkyriestudios/utils 12.37.0 → 12.38.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.
Files changed (193) hide show
  1. package/array/groupBy.d.ts +3 -3
  2. package/array/join.d.ts +2 -2
  3. package/array/split.d.ts +3 -3
  4. package/caching/LRU.d.ts +16 -10
  5. package/{array → cjs/array}/groupBy.js +16 -4
  6. package/{array → cjs/array}/join.js +15 -3
  7. package/{array → cjs/array}/split.js +16 -7
  8. package/cjs/caching/LRU.js +123 -0
  9. package/{caching → cjs/caching}/memoize.js +11 -5
  10. package/{date → cjs/date}/format.js +4 -1
  11. package/{date → cjs/date}/isFormat.js +4 -1
  12. package/esm/array/dedupe.js +52 -0
  13. package/esm/array/groupBy.js +43 -0
  14. package/esm/array/index.js +14 -0
  15. package/esm/array/is.js +4 -0
  16. package/esm/array/isNotEmpty.js +4 -0
  17. package/esm/array/join.js +58 -0
  18. package/esm/array/mapFn.js +22 -0
  19. package/esm/array/mapFnAsMap.js +21 -0
  20. package/esm/array/mapKey.js +22 -0
  21. package/esm/array/mapKeyAsMap.js +22 -0
  22. package/esm/array/mapPrimitive.js +33 -0
  23. package/esm/array/shuffle.js +10 -0
  24. package/esm/array/sort.js +137 -0
  25. package/esm/array/split.js +43 -0
  26. package/esm/boolean/index.js +1 -0
  27. package/esm/boolean/is.js +4 -0
  28. package/esm/caching/LRU.js +116 -0
  29. package/esm/caching/index.js +3 -0
  30. package/esm/caching/memoize.js +37 -0
  31. package/esm/date/addUTC.js +41 -0
  32. package/esm/date/convertToDate.js +12 -0
  33. package/esm/date/diff.js +34 -0
  34. package/esm/date/endOfUTC.js +50 -0
  35. package/esm/date/format.js +241 -0
  36. package/esm/date/index.js +15 -0
  37. package/esm/date/is.js +4 -0
  38. package/esm/date/isFormat.js +118 -0
  39. package/esm/date/isLeap.js +9 -0
  40. package/esm/date/nowUnix.js +4 -0
  41. package/esm/date/nowUnixMs.js +4 -0
  42. package/esm/date/setTimeUTC.js +10 -0
  43. package/esm/date/startOfUTC.js +50 -0
  44. package/esm/date/toUTC.js +7 -0
  45. package/esm/date/toUnix.js +7 -0
  46. package/esm/deep/freeze.js +21 -0
  47. package/esm/deep/get.js +84 -0
  48. package/esm/deep/index.js +8 -0
  49. package/esm/deep/seal.js +21 -0
  50. package/esm/deep/set.js +50 -0
  51. package/esm/equal.js +67 -0
  52. package/esm/formdata/index.js +2 -0
  53. package/esm/formdata/is.js +4 -0
  54. package/esm/formdata/toObject.js +89 -0
  55. package/esm/function/debounce.js +39 -0
  56. package/esm/function/index.js +9 -0
  57. package/esm/function/is.js +4 -0
  58. package/esm/function/isAsync.js +4 -0
  59. package/esm/function/noop.js +2 -0
  60. package/esm/function/noopresolve.js +4 -0
  61. package/esm/function/noopreturn.js +4 -0
  62. package/esm/function/sleep.js +6 -0
  63. package/esm/hash/fnv1A.js +51 -0
  64. package/esm/hash/guid.js +31 -0
  65. package/esm/hash/index.js +2 -0
  66. package/esm/is.js +63 -0
  67. package/esm/modules/PubSub.js +187 -0
  68. package/esm/modules/Scheduler.js +343 -0
  69. package/esm/modules/index.js +2 -0
  70. package/esm/number/index.js +37 -0
  71. package/esm/number/is.js +4 -0
  72. package/esm/number/isAbove.js +4 -0
  73. package/esm/number/isAboveOrEqual.js +4 -0
  74. package/esm/number/isBelow.js +4 -0
  75. package/esm/number/isBelowOrEqual.js +4 -0
  76. package/esm/number/isBetween.js +7 -0
  77. package/esm/number/isInteger.js +4 -0
  78. package/esm/number/isIntegerAbove.js +4 -0
  79. package/esm/number/isIntegerAboveOrEqual.js +4 -0
  80. package/esm/number/isIntegerBelow.js +4 -0
  81. package/esm/number/isIntegerBelowOrEqual.js +4 -0
  82. package/esm/number/isIntegerBetween.js +7 -0
  83. package/esm/number/isNumericalNaN.js +4 -0
  84. package/esm/number/randomBetween.js +7 -0
  85. package/esm/number/randomIntBetween.js +7 -0
  86. package/esm/number/round.js +10 -0
  87. package/esm/number/toPercentage.js +9 -0
  88. package/esm/object/define.js +7 -0
  89. package/esm/object/index.js +7 -0
  90. package/esm/object/is.js +4 -0
  91. package/esm/object/isNotEmpty.js +9 -0
  92. package/esm/object/merge.js +31 -0
  93. package/esm/object/omit.js +30 -0
  94. package/esm/object/pick.js +33 -0
  95. package/esm/regexp/index.js +3 -0
  96. package/esm/regexp/is.js +4 -0
  97. package/esm/regexp/sanitize.js +7 -0
  98. package/esm/string/humanizeBytes.js +15 -0
  99. package/esm/string/humanizeNumber.js +40 -0
  100. package/esm/string/index.js +7 -0
  101. package/esm/string/is.js +4 -0
  102. package/esm/string/isBetween.js +12 -0
  103. package/esm/string/isNotEmpty.js +20 -0
  104. package/esm/string/shorten.js +18 -0
  105. package/index.d.ts +19 -15
  106. package/package.json +192 -850
  107. package/caching/LRU.js +0 -72
  108. /package/{array → cjs/array}/dedupe.js +0 -0
  109. /package/{array → cjs/array}/index.js +0 -0
  110. /package/{array → cjs/array}/is.js +0 -0
  111. /package/{array → cjs/array}/isNotEmpty.js +0 -0
  112. /package/{array → cjs/array}/mapFn.js +0 -0
  113. /package/{array → cjs/array}/mapFnAsMap.js +0 -0
  114. /package/{array → cjs/array}/mapKey.js +0 -0
  115. /package/{array → cjs/array}/mapKeyAsMap.js +0 -0
  116. /package/{array → cjs/array}/mapPrimitive.js +0 -0
  117. /package/{array → cjs/array}/shuffle.js +0 -0
  118. /package/{array → cjs/array}/sort.js +0 -0
  119. /package/{boolean → cjs/boolean}/index.js +0 -0
  120. /package/{boolean → cjs/boolean}/is.js +0 -0
  121. /package/{caching → cjs/caching}/index.js +0 -0
  122. /package/{date → cjs/date}/addUTC.js +0 -0
  123. /package/{date → cjs/date}/convertToDate.js +0 -0
  124. /package/{date → cjs/date}/diff.js +0 -0
  125. /package/{date → cjs/date}/endOfUTC.js +0 -0
  126. /package/{date → cjs/date}/index.js +0 -0
  127. /package/{date → cjs/date}/is.js +0 -0
  128. /package/{date → cjs/date}/isLeap.js +0 -0
  129. /package/{date → cjs/date}/nowUnix.js +0 -0
  130. /package/{date → cjs/date}/nowUnixMs.js +0 -0
  131. /package/{date → cjs/date}/setTimeUTC.js +0 -0
  132. /package/{date → cjs/date}/startOfUTC.js +0 -0
  133. /package/{date → cjs/date}/toUTC.js +0 -0
  134. /package/{date → cjs/date}/toUnix.js +0 -0
  135. /package/{deep → cjs/deep}/freeze.js +0 -0
  136. /package/{deep → cjs/deep}/get.js +0 -0
  137. /package/{deep → cjs/deep}/index.js +0 -0
  138. /package/{deep → cjs/deep}/seal.js +0 -0
  139. /package/{deep → cjs/deep}/set.js +0 -0
  140. /package/{equal.js → cjs/equal.js} +0 -0
  141. /package/{formdata → cjs/formdata}/index.js +0 -0
  142. /package/{formdata → cjs/formdata}/is.js +0 -0
  143. /package/{formdata → cjs/formdata}/toObject.js +0 -0
  144. /package/{function → cjs/function}/debounce.js +0 -0
  145. /package/{function → cjs/function}/index.js +0 -0
  146. /package/{function → cjs/function}/is.js +0 -0
  147. /package/{function → cjs/function}/isAsync.js +0 -0
  148. /package/{function → cjs/function}/noop.js +0 -0
  149. /package/{function → cjs/function}/noopresolve.js +0 -0
  150. /package/{function → cjs/function}/noopreturn.js +0 -0
  151. /package/{function → cjs/function}/sleep.js +0 -0
  152. /package/{hash → cjs/hash}/fnv1A.js +0 -0
  153. /package/{hash → cjs/hash}/guid.js +0 -0
  154. /package/{hash → cjs/hash}/index.js +0 -0
  155. /package/{is.js → cjs/is.js} +0 -0
  156. /package/{modules → cjs/modules}/PubSub.js +0 -0
  157. /package/{modules → cjs/modules}/Scheduler.js +0 -0
  158. /package/{modules → cjs/modules}/index.js +0 -0
  159. /package/{number → cjs/number}/index.js +0 -0
  160. /package/{number → cjs/number}/is.js +0 -0
  161. /package/{number → cjs/number}/isAbove.js +0 -0
  162. /package/{number → cjs/number}/isAboveOrEqual.js +0 -0
  163. /package/{number → cjs/number}/isBelow.js +0 -0
  164. /package/{number → cjs/number}/isBelowOrEqual.js +0 -0
  165. /package/{number → cjs/number}/isBetween.js +0 -0
  166. /package/{number → cjs/number}/isInteger.js +0 -0
  167. /package/{number → cjs/number}/isIntegerAbove.js +0 -0
  168. /package/{number → cjs/number}/isIntegerAboveOrEqual.js +0 -0
  169. /package/{number → cjs/number}/isIntegerBelow.js +0 -0
  170. /package/{number → cjs/number}/isIntegerBelowOrEqual.js +0 -0
  171. /package/{number → cjs/number}/isIntegerBetween.js +0 -0
  172. /package/{number → cjs/number}/isNumericalNaN.js +0 -0
  173. /package/{number → cjs/number}/randomBetween.js +0 -0
  174. /package/{number → cjs/number}/randomIntBetween.js +0 -0
  175. /package/{number → cjs/number}/round.js +0 -0
  176. /package/{number → cjs/number}/toPercentage.js +0 -0
  177. /package/{object → cjs/object}/define.js +0 -0
  178. /package/{object → cjs/object}/index.js +0 -0
  179. /package/{object → cjs/object}/is.js +0 -0
  180. /package/{object → cjs/object}/isNotEmpty.js +0 -0
  181. /package/{object → cjs/object}/merge.js +0 -0
  182. /package/{object → cjs/object}/omit.js +0 -0
  183. /package/{object → cjs/object}/pick.js +0 -0
  184. /package/{regexp → cjs/regexp}/index.js +0 -0
  185. /package/{regexp → cjs/regexp}/is.js +0 -0
  186. /package/{regexp → cjs/regexp}/sanitize.js +0 -0
  187. /package/{string → cjs/string}/humanizeBytes.js +0 -0
  188. /package/{string → cjs/string}/humanizeNumber.js +0 -0
  189. /package/{string → cjs/string}/index.js +0 -0
  190. /package/{string → cjs/string}/is.js +0 -0
  191. /package/{string → cjs/string}/isBetween.js +0 -0
  192. /package/{string → cjs/string}/isNotEmpty.js +0 -0
  193. /package/{string → cjs/string}/shorten.js +0 -0
@@ -0,0 +1,241 @@
1
+ import { convertToDate } from './convertToDate';
2
+ import LRU from '../caching/LRU';
3
+ const WEEK_STARTS = {
4
+ mon: 'mon',
5
+ sun: 'sun',
6
+ sat: 'sat',
7
+ };
8
+ let DEFAULT_LOCALE = 'en-US';
9
+ let DEFAULT_TZ = 'UTC';
10
+ let DEFAULT_SOW = 'mon';
11
+ try {
12
+ DEFAULT_TZ = Intl.DateTimeFormat().resolvedOptions().timeZone;
13
+ }
14
+ catch {
15
+ }
16
+ const ESCAPE_RGX = /\[[\s\S]+?]/g;
17
+ const intl_formatters = new LRU({ max_size: 100 });
18
+ const spec_cache = new LRU({ max_size: 100 });
19
+ const zone_offset_cache = new LRU({ max_size: 100 });
20
+ function WeekNr(d, sow) {
21
+ switch (sow) {
22
+ case 'sun':
23
+ case 'sat': {
24
+ const OFFSET = sow === 'sat' ? 1 : 0;
25
+ const jan1 = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
26
+ const near = new Date(d.getTime() - (((d.getDay() + OFFSET) % 7) * 86400000));
27
+ const first = new Date(jan1.getTime() - (((jan1.getDay() + OFFSET) % 7) * 86400000));
28
+ return 1 + Math.floor((near.valueOf() - first.valueOf()) / 604800000);
29
+ }
30
+ default: {
31
+ const date = new Date(d.valueOf());
32
+ date.setDate(date.getDate() - ((d.getDay() + 6) % 7) + 3);
33
+ const date_thu = date.valueOf();
34
+ date.setMonth(0, 1);
35
+ if (date.getDay() !== 4)
36
+ date.setMonth(0, (1 + ((4 - date.getDay()) + 7)) % 7);
37
+ return 1 + Math.ceil((date_thu - date.valueOf()) / 604800000);
38
+ }
39
+ }
40
+ }
41
+ function toZone(d, zone) {
42
+ const year = d.getUTCFullYear();
43
+ const month = d.getUTCMonth();
44
+ const day = d.getUTCDate();
45
+ const time = d.getTime();
46
+ const daysInMonths = [31, (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
47
+ let doy = day;
48
+ for (let i = 0; i <= month; i++)
49
+ doy += daysInMonths[i];
50
+ const ckey = zone + ':' + year + ':' + doy;
51
+ const cached = zone_offset_cache.get(ckey);
52
+ if (cached !== undefined)
53
+ return new Date(time + cached);
54
+ let zone_time = null;
55
+ try {
56
+ zone_time = new Date(d.toLocaleString(DEFAULT_LOCALE, { timeZone: zone })).getTime() + d.getMilliseconds();
57
+ }
58
+ catch {
59
+ throw new Error(`format: Invalid zone passed - ${zone}`);
60
+ }
61
+ const offset = zone_time - time;
62
+ zone_offset_cache.set(ckey, offset);
63
+ return new Date(time + offset);
64
+ }
65
+ function runIntl(loc, token, props, val) {
66
+ const hash = loc + ':' + token;
67
+ let formatter = intl_formatters.get(hash);
68
+ if (!formatter) {
69
+ try {
70
+ formatter = new Intl.DateTimeFormat(loc, props);
71
+ intl_formatters.set(hash, formatter);
72
+ }
73
+ catch {
74
+ throw new Error(`format: Failed to run conversion for ${token} with locale ${loc}`);
75
+ }
76
+ }
77
+ return formatter.format(val);
78
+ }
79
+ const Tokens = [
80
+ ['YYYY', d => d.getFullYear()],
81
+ ['Q', d => ((d.getMonth() + 3) / 3) | 0],
82
+ ['MMMM', (d, loc) => runIntl(loc, 'MMMM', { month: 'long' }, d)],
83
+ ['MMM', (d, loc) => runIntl(loc, 'MMM', { month: 'short' }, d)],
84
+ ['MM', d => {
85
+ const val = d.getMonth() + 1;
86
+ return (val < 10 ? '0' : '') + val;
87
+ }],
88
+ ['M', d => d.getMonth() + 1],
89
+ ['WW', (d, loc, sow) => {
90
+ const val = WeekNr(d, sow);
91
+ return (val < 10 ? '0' : '') + val;
92
+ }],
93
+ ['W', (d, loc, sow) => WeekNr(d, sow)],
94
+ ['DD', d => {
95
+ const val = d.getDate();
96
+ return (val < 10 ? '0' : '') + val;
97
+ }],
98
+ ['D', d => d.getDate()],
99
+ ['dddd', (d, loc) => runIntl(loc, 'dddd', { weekday: 'long' }, d)],
100
+ ['ddd', (d, loc) => runIntl(loc, 'ddd', { weekday: 'short' }, d)],
101
+ ['HH', d => {
102
+ const val = d.getHours();
103
+ return (val < 10 ? '0' : '') + val;
104
+ }],
105
+ ['H', d => d.getHours()],
106
+ ['hh', d => {
107
+ const val = ((d.getHours() + 11) % 12) + 1;
108
+ return (val < 10 ? '0' : '') + val;
109
+ }],
110
+ ['h', d => ((d.getHours() + 11) % 12) + 1],
111
+ ['mm', d => {
112
+ const val = d.getMinutes();
113
+ return (val < 10 ? '0' : '') + val;
114
+ }],
115
+ ['m', d => d.getMinutes()],
116
+ ['ss', d => {
117
+ const val = d.getSeconds();
118
+ return (val < 10 ? '0' : '') + val;
119
+ }],
120
+ ['s', d => d.getSeconds()],
121
+ ['SSS', d => {
122
+ const val = d.getMilliseconds();
123
+ return val < 10
124
+ ? '00' + val
125
+ : val < 100
126
+ ? '0' + val
127
+ : val;
128
+ }],
129
+ ['A', d => d.getHours() < 12 ? 'AM' : 'PM'],
130
+ ['a', d => d.getHours() < 12 ? 'am' : 'pm'],
131
+ ['l', (d, loc) => runIntl(loc, 'l', { dateStyle: 'short' }, d)],
132
+ ['L', (d, loc) => runIntl(loc, 'L', { dateStyle: 'medium' }, d)],
133
+ ['t', (d, loc) => runIntl(loc, 't', { timeStyle: 'short' }, d)],
134
+ ['T', (d, loc) => runIntl(loc, 'T', { timeStyle: 'medium' }, d)],
135
+ ]
136
+ .map(el => [el[0], el[1], el[0].length])
137
+ .sort((a, b) => a[0].length > b[0].length ? -1 : 1);
138
+ function getSpecChain(spec) {
139
+ const cached = spec_cache.get(spec);
140
+ if (cached !== undefined)
141
+ return cached;
142
+ let base = spec;
143
+ const repl = [];
144
+ let repl_len = 0;
145
+ if (base.indexOf('[') >= 0) {
146
+ base = base.replace(ESCAPE_RGX, match => {
147
+ const escape_token = '$' + repl_len++ + '$';
148
+ repl.push([escape_token, match.slice(1, -1)]);
149
+ return escape_token;
150
+ });
151
+ }
152
+ const chain = [];
153
+ const matched_positions = new Set();
154
+ for (let i = 0; i < Tokens.length; i++) {
155
+ const [token] = Tokens[i];
156
+ let pos = base.indexOf(token);
157
+ const token_len = token.length;
158
+ while (pos !== -1) {
159
+ if (!matched_positions.has(pos)) {
160
+ chain.push(Tokens[i]);
161
+ for (let j = 0; j < token_len; j++) {
162
+ matched_positions.add(pos + j);
163
+ }
164
+ }
165
+ pos = base.indexOf(token, pos + 1);
166
+ }
167
+ }
168
+ const chain_len = chain.length;
169
+ const result = chain_len ? { base, chain, chain_len, repl } : null;
170
+ spec_cache.set(spec, result);
171
+ return result;
172
+ }
173
+ const SPEC_ALIASES = {
174
+ ISO: 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]',
175
+ };
176
+ function format(val, spec, locale = DEFAULT_LOCALE, zone = DEFAULT_TZ, sow = DEFAULT_SOW) {
177
+ const n_val = convertToDate(val);
178
+ if (n_val === null)
179
+ throw new TypeError('format: val must be a Date');
180
+ if (typeof spec !== 'string')
181
+ throw new TypeError('format: spec must be a string');
182
+ if (typeof locale !== 'string')
183
+ throw new TypeError('format: locale must be a string');
184
+ if (typeof zone !== 'string')
185
+ throw new TypeError('format: zone must be a string');
186
+ const n_spec = getSpecChain(SPEC_ALIASES[spec] || spec);
187
+ if (!n_spec)
188
+ return n_val.toISOString();
189
+ const d = toZone(n_val, zone);
190
+ let base = n_spec.base;
191
+ const repl = [...n_spec.repl];
192
+ let repl_len = n_spec.repl.length;
193
+ for (let i = 0; i < n_spec.chain_len; i++) {
194
+ const el = n_spec.chain[i];
195
+ let pos = base.indexOf(el[0]);
196
+ const token_val = el[1](d, locale, sow);
197
+ while (pos !== -1) {
198
+ const key = '$' + repl_len++ + '$';
199
+ repl.push([key, token_val]);
200
+ base = base.slice(0, pos) + key + base.slice(pos + el[2]);
201
+ pos = base.indexOf(el[0], pos + el[2]);
202
+ }
203
+ }
204
+ for (let i = 0; i < repl_len; i++) {
205
+ base = base.replace(repl[i][0], repl[i][1]);
206
+ }
207
+ return base;
208
+ }
209
+ format.getLocale = function () {
210
+ return DEFAULT_LOCALE;
211
+ };
212
+ format.setLocale = function (locale) {
213
+ const normalized = typeof locale === 'string' ? locale.trim() : false;
214
+ if (!normalized)
215
+ throw new Error('format/setLocale: locale should be a string');
216
+ DEFAULT_LOCALE = normalized;
217
+ };
218
+ format.getZone = function () {
219
+ return DEFAULT_TZ;
220
+ };
221
+ format.setZone = function (zone) {
222
+ if (typeof zone !== 'string')
223
+ throw new Error('format/setZone: zone should be a string');
224
+ try {
225
+ new Intl.DateTimeFormat('en-US', { timeZone: zone });
226
+ DEFAULT_TZ = zone;
227
+ }
228
+ catch {
229
+ throw new Error(`format/setZone: '${zone}' is not a valid zone`);
230
+ }
231
+ };
232
+ format.getStartOfWeek = function () {
233
+ return DEFAULT_SOW;
234
+ };
235
+ format.setStartOfWeek = function (sow) {
236
+ if (typeof sow !== 'string' ||
237
+ !Object.values(WEEK_STARTS).includes(sow))
238
+ throw new Error('format/setStartOfWeek: sow should be a valid start of week');
239
+ DEFAULT_SOW = sow;
240
+ };
241
+ export { format, format as default };
@@ -0,0 +1,15 @@
1
+ export { addUTC } from './addUTC';
2
+ export { convertToDate } from './convertToDate';
3
+ export { diff } from './diff';
4
+ export { endOfUTC } from './endOfUTC';
5
+ export { format } from './format';
6
+ export { isLeap } from './isLeap';
7
+ export { nowUnix } from './nowUnix';
8
+ export { nowUnixMs } from './nowUnixMs';
9
+ export { setTimeUTC } from './setTimeUTC';
10
+ export { startOfUTC } from './startOfUTC';
11
+ export { toUnix } from './toUnix';
12
+ export { toUTC } from './toUTC';
13
+ export { isDateFormat as isFormat } from './isFormat';
14
+ export { isDateFormat } from './isFormat';
15
+ export { isDate } from './is';
package/esm/date/is.js ADDED
@@ -0,0 +1,4 @@
1
+ function isDate(val) {
2
+ return val instanceof Date && !isNaN(val);
3
+ }
4
+ export { isDate, isDate as default };
@@ -0,0 +1,118 @@
1
+ import LRU from '../caching/LRU';
2
+ const SPECIAL_CHARS = /[.*+?^${}()|[\]\\]/g;
3
+ const TOKENS = [
4
+ ['YYYY', /\d{4}/.source, (raw, context) => {
5
+ context.year = parseInt(raw, 10);
6
+ return context.year > 0;
7
+ }],
8
+ ['MM', /(?:0[1-9]|1[0-2])/.source, (raw, context) => {
9
+ context.month = parseInt(raw, 10);
10
+ return context.month >= 1 && context.month <= 12;
11
+ }],
12
+ ['DD', /(?:0[1-9]|[12][0-9]|3[01])/.source, (raw, context) => {
13
+ context.day = parseInt(raw, 10);
14
+ return context.day >= 1 && context.day <= 31;
15
+ }],
16
+ ['HH', /(?:[01][0-9]|2[0-3])/.source, (raw, context) => {
17
+ context.hour = parseInt(raw, 10);
18
+ return context.hour >= 0 && context.hour <= 23;
19
+ }],
20
+ ['mm', /[0-5][0-9]/.source, () => true],
21
+ ['ss', /[0-5][0-9]/.source, () => true],
22
+ ['SSS', /\d{3}/.source, () => true],
23
+ ['Q', /[1-4]/.source, () => true],
24
+ ['A', /(?:AM|PM)/.source, (raw, context) => {
25
+ context.is12 = 1;
26
+ return raw === 'AM' || raw === 'PM';
27
+ }],
28
+ ['a', /(?:am|pm)/.source, (raw, context) => {
29
+ context.is12 = 1;
30
+ return raw === 'am' || raw === 'pm';
31
+ }],
32
+ ['Z', /Z|[+-](?:0[0-9]|1[0-4]):[0-5][0-9]/.source, raw => {
33
+ if (raw === 'Z')
34
+ return true;
35
+ let hour = parseInt(raw[1] + raw[2], 10);
36
+ if (raw[0] === '-')
37
+ hour = -hour;
38
+ const minutes = parseInt(raw[4] + raw[5], 10);
39
+ if (hour === 14 || hour === -12)
40
+ return minutes === 0;
41
+ return hour >= -11 && hour < 14 && [0, 15, 30, 45].indexOf(minutes) >= 0;
42
+ }],
43
+ ];
44
+ const SPEC_ALIASES = {
45
+ ISO: 'YYYY-MM-DDTHH:mm:ss{.SSS}Z',
46
+ };
47
+ const spec_pat_cache = new LRU({ max_size: 100 });
48
+ function compileSpec(spec, is_chunk = false) {
49
+ let cached = spec_pat_cache.get(spec);
50
+ if (cached !== undefined)
51
+ return cached;
52
+ const tokens = [];
53
+ let pat = '';
54
+ let cursor = 0;
55
+ while (cursor < spec.length) {
56
+ if (spec[cursor] === '[') {
57
+ const end_idx = spec.indexOf(']', cursor);
58
+ if (end_idx === -1)
59
+ throw new Error('isDateFormat: Unmatched [ in format string');
60
+ pat += spec.slice(cursor + 1, end_idx).replace(SPECIAL_CHARS, '\\$&');
61
+ cursor = end_idx + 1;
62
+ }
63
+ else if (spec[cursor] === '{') {
64
+ const end_idx = spec.indexOf('}', cursor);
65
+ if (end_idx === -1)
66
+ throw new Error('isDateFormat: Unmatched { in format string');
67
+ const compiled = compileSpec(spec.slice(cursor + 1, end_idx), true);
68
+ pat += '(?:' + compiled.rgx.source + ')?';
69
+ tokens.push(...compiled.tokens);
70
+ cursor = end_idx + 1;
71
+ }
72
+ else {
73
+ const token_idx = TOKENS.findIndex(([token_key]) => spec.startsWith(token_key, cursor));
74
+ if (token_idx >= 0) {
75
+ const [token_key, token_rgx] = TOKENS[token_idx];
76
+ pat += '(' + token_rgx + ')';
77
+ tokens.push(token_idx);
78
+ cursor += token_key.length;
79
+ }
80
+ else {
81
+ pat += spec[cursor].replace(SPECIAL_CHARS, '\\$&');
82
+ cursor++;
83
+ }
84
+ }
85
+ }
86
+ cached = { rgx: is_chunk ? RegExp(pat) : RegExp('^' + pat + '$'), tokens };
87
+ spec_pat_cache.set(spec, cached);
88
+ return cached;
89
+ }
90
+ function isDateFormat(input, spec) {
91
+ if (typeof input !== 'string')
92
+ return false;
93
+ if (typeof spec !== 'string')
94
+ throw new TypeError('isDateFormat: spec must be a string');
95
+ const { tokens, rgx } = compileSpec(SPEC_ALIASES[spec] || spec);
96
+ if (!tokens.length)
97
+ return false;
98
+ const patMatch = rgx.exec(input);
99
+ if (!patMatch)
100
+ return false;
101
+ const matches = patMatch.slice(1);
102
+ const context = {};
103
+ for (let i = 0; i < matches.length; i++) {
104
+ const match = matches[i];
105
+ if (match !== undefined && !TOKENS[tokens[i]][2](match, context))
106
+ return false;
107
+ }
108
+ const { is12, day, month, year } = context;
109
+ if (day && month) {
110
+ const date = new Date(year || 2024, month - 1, day);
111
+ if (date.getDate() !== day || date.getMonth() !== month - 1)
112
+ return false;
113
+ }
114
+ if (is12 && 'hour' in context && context.hour > 11)
115
+ return false;
116
+ return true;
117
+ }
118
+ export { isDateFormat, isDateFormat as default };
@@ -0,0 +1,9 @@
1
+ import { convertToDate } from './convertToDate';
2
+ function isLeap(val) {
3
+ const n_val = convertToDate(val);
4
+ if (n_val === null)
5
+ return false;
6
+ const year = n_val.getUTCFullYear();
7
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
8
+ }
9
+ export { isLeap, isLeap as default };
@@ -0,0 +1,4 @@
1
+ function nowUnix() {
2
+ return (Date.now() / 1000) | 0;
3
+ }
4
+ export { nowUnix, nowUnix as default };
@@ -0,0 +1,4 @@
1
+ function nowUnixMs() {
2
+ return Date.now();
3
+ }
4
+ export { nowUnixMs, nowUnixMs as default };
@@ -0,0 +1,10 @@
1
+ import { convertToDate } from './convertToDate';
2
+ import { isIntegerBetween } from '../number/isIntegerBetween';
3
+ function setTimeUTC(val, props) {
4
+ const n_val = convertToDate(val);
5
+ if (n_val === null)
6
+ throw new TypeError('setTimeUTC requires a date object');
7
+ const { hour, minute, second, millisecond } = props || {};
8
+ return new Date(Date.UTC(n_val.getUTCFullYear(), n_val.getUTCMonth(), n_val.getUTCDate(), isIntegerBetween(hour, 0, 23) ? hour : n_val.getUTCHours(), isIntegerBetween(minute, 0, 59) ? minute : n_val.getUTCMinutes(), isIntegerBetween(second, 0, 59) ? second : n_val.getUTCSeconds(), isIntegerBetween(millisecond, 0, 999) ? millisecond : n_val.getUTCMilliseconds()));
9
+ }
10
+ export { setTimeUTC, setTimeUTC as default };
@@ -0,0 +1,50 @@
1
+ import { convertToDate } from './convertToDate';
2
+ const WEEK_START = new Map([
3
+ ['week', 1],
4
+ ['week_sun', 0],
5
+ ['week_mon', 1],
6
+ ['week_tue', 2],
7
+ ['week_wed', 3],
8
+ ['week_thu', 4],
9
+ ['week_fri', 5],
10
+ ['week_sat', 6],
11
+ ]);
12
+ function startOfUTC(val, key = 'millisecond') {
13
+ const n_val = convertToDate(val);
14
+ if (n_val === null)
15
+ throw new TypeError('startOfUTC requires a date object');
16
+ const year = n_val.getUTCFullYear();
17
+ switch (key) {
18
+ case 'year':
19
+ return new Date(Date.UTC(year, 0));
20
+ case 'quarter': {
21
+ const UTC_MONTH = n_val.getUTCMonth();
22
+ return new Date(Date.UTC(year, UTC_MONTH - (UTC_MONTH % 3)));
23
+ }
24
+ case 'month':
25
+ return new Date(Date.UTC(year, n_val.getUTCMonth()));
26
+ case 'week':
27
+ case 'week_sun':
28
+ case 'week_mon':
29
+ case 'week_tue':
30
+ case 'week_wed':
31
+ case 'week_thu':
32
+ case 'week_fri':
33
+ case 'week_sat': {
34
+ const UTC_DAY = n_val.getUTCDay();
35
+ const UTC_SOD = WEEK_START.get(key);
36
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate() - (UTC_DAY < UTC_SOD ? (7 - UTC_SOD) + UTC_DAY : UTC_DAY - UTC_SOD)));
37
+ }
38
+ case 'day':
39
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate()));
40
+ case 'hour':
41
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate(), n_val.getUTCHours()));
42
+ case 'minute':
43
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate(), n_val.getUTCHours(), n_val.getUTCMinutes()));
44
+ case 'second':
45
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate(), n_val.getUTCHours(), n_val.getUTCMinutes(), n_val.getUTCSeconds()));
46
+ default:
47
+ return new Date(Date.UTC(year, n_val.getUTCMonth(), n_val.getUTCDate(), n_val.getUTCHours(), n_val.getUTCMinutes(), n_val.getUTCSeconds(), n_val.getUTCMilliseconds()));
48
+ }
49
+ }
50
+ export { startOfUTC, startOfUTC as default };
@@ -0,0 +1,7 @@
1
+ import { isDate } from './is';
2
+ function toUTC(val) {
3
+ if (!isDate(val))
4
+ throw new TypeError('toUTC requires a date object');
5
+ return new Date(Date.UTC(val.getUTCFullYear(), val.getUTCMonth(), val.getUTCDate(), val.getUTCHours(), val.getUTCMinutes(), val.getUTCSeconds(), val.getUTCMilliseconds()));
6
+ }
7
+ export { toUTC, toUTC as default };
@@ -0,0 +1,7 @@
1
+ import { isDate } from './is';
2
+ function toUnix(val) {
3
+ if (!isDate(val))
4
+ throw new TypeError('toUnix requires a date object');
5
+ return (val.valueOf() / 1000) | 0;
6
+ }
7
+ export { toUnix, toUnix as default };
@@ -0,0 +1,21 @@
1
+ function deep(obj) {
2
+ if (Array.isArray(obj)) {
3
+ for (let i = 0; i < obj.length; i++)
4
+ deep(obj[i]);
5
+ }
6
+ else {
7
+ for (const key in obj) {
8
+ if (Object.prototype.toString.call(obj[key]) === '[object Object]' ||
9
+ Array.isArray(obj[key]))
10
+ deep(obj[key]);
11
+ }
12
+ }
13
+ return Object.freeze(obj);
14
+ }
15
+ function deepFreeze(obj) {
16
+ if (Object.prototype.toString.call(obj) !== '[object Object]' &&
17
+ !Array.isArray(obj))
18
+ throw new TypeError('Only objects/arrays can be frozen');
19
+ return deep(obj);
20
+ }
21
+ export { deepFreeze, deepFreeze as default };
@@ -0,0 +1,84 @@
1
+ function deepGet(obj, path, get_parent = false) {
2
+ if (Object.prototype.toString.call(obj) !== '[object Object]' &&
3
+ !Array.isArray(obj))
4
+ throw new TypeError('deepGet: Requires object or array');
5
+ if (typeof path !== 'string' ||
6
+ !path.length)
7
+ throw new TypeError('deepGet: Invalid path provided');
8
+ const nodes = [];
9
+ let node = obj;
10
+ let key = '';
11
+ for (let i = 0; i < path.length; i++) {
12
+ const char = path[i];
13
+ switch (char) {
14
+ case '[':
15
+ case ']':
16
+ case '.':
17
+ if (!key)
18
+ break;
19
+ if (Array.isArray(node)) {
20
+ if (!isNaN(Number(key))) {
21
+ const ix = parseInt(key, 10);
22
+ if (ix < 0 || ix > node.length - 1)
23
+ return undefined;
24
+ node = node[ix];
25
+ nodes.push(node);
26
+ }
27
+ else {
28
+ const extracted = [];
29
+ for (let y = 0; y < node.length; y++) {
30
+ const el = deepGet(node[y], key);
31
+ if (el !== undefined) {
32
+ extracted.push(...Array.isArray(el) ? el : [el]);
33
+ }
34
+ }
35
+ node = extracted;
36
+ nodes.push(node);
37
+ }
38
+ }
39
+ else if (typeof node === 'object' && node !== null) {
40
+ node = node[key];
41
+ nodes.push(node);
42
+ }
43
+ key = '';
44
+ break;
45
+ default:
46
+ key += char;
47
+ break;
48
+ }
49
+ }
50
+ if (key) {
51
+ if (Array.isArray(node)) {
52
+ if (!isNaN(Number(key))) {
53
+ const ix = parseInt(key, 10);
54
+ if (ix < 0 || ix > node.length - 1)
55
+ return undefined;
56
+ node = node[ix];
57
+ nodes.push(node);
58
+ }
59
+ else {
60
+ const extracted = [];
61
+ for (let i = 0; i < node.length; i++) {
62
+ const val = node[i]?.[key];
63
+ if (val !== undefined)
64
+ extracted.push(...Array.isArray(val) ? val : [val]);
65
+ }
66
+ node = extracted.length ? extracted : undefined;
67
+ nodes.push(node);
68
+ }
69
+ }
70
+ else if (typeof node === 'object' && node !== null) {
71
+ node = node[key];
72
+ nodes.push(node);
73
+ if (node === undefined)
74
+ return undefined;
75
+ }
76
+ else {
77
+ return undefined;
78
+ }
79
+ }
80
+ if (get_parent)
81
+ nodes.pop();
82
+ return nodes.length ? nodes.pop() : obj;
83
+ }
84
+ export { deepGet, deepGet as default };
@@ -0,0 +1,8 @@
1
+ export { deepFreeze as freeze } from './freeze';
2
+ export { deepFreeze } from './freeze';
3
+ export { deepGet as get } from './get';
4
+ export { deepGet } from './get';
5
+ export { deepSeal as seal } from './seal';
6
+ export { deepSeal } from './seal';
7
+ export { deepSet as set } from './set';
8
+ export { deepSet } from './set';
@@ -0,0 +1,21 @@
1
+ function deep(obj) {
2
+ if (Array.isArray(obj)) {
3
+ for (let i = 0; i < obj.length; i++)
4
+ deep(obj[i]);
5
+ }
6
+ else {
7
+ for (const key in obj) {
8
+ if (Object.prototype.toString.call(obj[key]) === '[object Object]' ||
9
+ Array.isArray(obj[key]))
10
+ deep(obj[key]);
11
+ }
12
+ }
13
+ return Object.seal(obj);
14
+ }
15
+ function deepSeal(obj) {
16
+ if (Object.prototype.toString.call(obj) !== '[object Object]' &&
17
+ !Array.isArray(obj))
18
+ throw new TypeError('Only objects/arrays can be sealed');
19
+ return deep(obj);
20
+ }
21
+ export { deepSeal, deepSeal as default };
@@ -0,0 +1,50 @@
1
+ const RGX_MALICIOUS = /__proto__|constructor|prototype/;
2
+ function deepSet(obj, path, value, define = false) {
3
+ if (Object.prototype.toString.call(obj) !== '[object Object]' &&
4
+ !Array.isArray(obj))
5
+ throw new TypeError('Deepset is only supported for objects');
6
+ if (typeof path !== 'string')
7
+ throw new TypeError('No path was given');
8
+ if (RGX_MALICIOUS.test(path))
9
+ throw new TypeError('Malicious path provided');
10
+ const path_s = path.trim();
11
+ if (!path_s.length)
12
+ throw new TypeError('No path was given');
13
+ const parts = path_s
14
+ .replace(/\[/g, '.')
15
+ .replace(/(\.){2,}/g, '.')
16
+ .replace(/(^\.|\.$|\])/g, '')
17
+ .split('.');
18
+ const last_part_ix = parts.length - 1;
19
+ for (let i = 0; i < last_part_ix; i++) {
20
+ if (Array.isArray(obj)) {
21
+ const idx = parseInt(parts[i]);
22
+ if (!Number.isInteger(idx) || idx < 0)
23
+ throw new TypeError('Invalid path provided');
24
+ if (!obj[idx])
25
+ obj[idx] = {};
26
+ obj = obj[idx];
27
+ }
28
+ else {
29
+ if (!obj[parts[i]])
30
+ obj[parts[i]] = {};
31
+ obj = obj[parts[i]];
32
+ }
33
+ }
34
+ if (!Array.isArray(obj) && Object.prototype.toString.call(obj) !== '[object Object]')
35
+ return false;
36
+ if (define) {
37
+ Object.defineProperty(obj, parts[last_part_ix], value);
38
+ }
39
+ else if (Array.isArray(obj)) {
40
+ const idx = parseInt(parts[last_part_ix]);
41
+ if (!Number.isInteger(idx) || idx < 0)
42
+ throw new TypeError('Invalid path provided');
43
+ obj[idx] = value;
44
+ }
45
+ else {
46
+ obj[parts[last_part_ix]] = value;
47
+ }
48
+ return true;
49
+ }
50
+ export { deepSet, deepSet as default };