@valkyriestudios/utils 12.12.0 → 12.13.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 CHANGED
@@ -404,6 +404,10 @@ Available tokens for usage in spec:
404
404
  | `SSS` | Milliseconds as 3-digit | 000 001 ... 998 999 |
405
405
  | `A` | Uppercase AM/PM | AM ... PM |
406
406
  | `a` | Lowercase AM/PM | am ... pm |
407
+ | `l` | Locale-specific short Date | 15/07/2024 |
408
+ | `L` | Locale-Specific date | 15 jul 2024 |
409
+ | `t` | Locale-specific short time | 10:28 AM |
410
+ | `T` | Locale-specific time with seconds | 10:28:30 AM |
407
411
 
408
412
  ```typescript
409
413
  format(new Date('2023-01-10T14:30:00Z'), '[Today is] dddd, MMMM D, YYYY [at] h:mm A', 'en', 'Europe/Brussels');
package/array/sort.d.ts CHANGED
@@ -17,7 +17,14 @@ interface sortOptions {
17
17
  }
18
18
  type sortByFunction = (el: Record<string, any>) => string;
19
19
  /**
20
- * Sort an array of objects, uses an implementation of Tony Hoare's quicksort
20
+ * Sort an array of objects.
21
+ *
22
+ * The internals of this function swap between insertion and quicksort depending on the use-case.
23
+ * Insertion sort is used for smaller arrays and quicksort is used for larger arrays.
24
+ *
25
+ * The threshold for insertion sort is 10 elements.
26
+ *
27
+ * The quicksort implementation is based on Tony Hoare's quicksort
21
28
  * (https://cs.stanford.edu/people/eroberts/courses/soco/projects/2008-09/tony-hoare/quicksort.html)
22
29
  *
23
30
  * Example:
@@ -43,10 +50,10 @@ type sortByFunction = (el: Record<string, any>) => string;
43
50
  * Output:
44
51
  * [{test: 'Pony'}, {test: 'Peter'}, {test: 'JOHn'}, {test: 'Joe'}]
45
52
  *
46
- * @param val - Array to sort
47
- * @param by - Either a string (key) or a function
48
- * @param dir - (default='asc') Direction to sort in (asc or desc)
49
- * @param opts - Sort options
53
+ * @param {Array} val - Array to sort
54
+ * @param {string|sortByFunction} by - Either a string (key) or a function
55
+ * @param {'desc'|'asc'} dir - (default='asc') Direction to sort in (asc or desc)
56
+ * @param {sortOptions} opts - Sort options
50
57
  *
51
58
  * @returns Sorted array
52
59
  * @throws {Error}
package/array/sort.js CHANGED
@@ -3,100 +3,97 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sort = sort;
4
4
  exports.default = sort;
5
5
  const isNotEmpty_1 = require("../object/isNotEmpty");
6
- function partition(arr, start_ix, end_ix) {
7
- const pivot_val = arr[Math.floor((start_ix + end_ix) / 2)].t;
8
- while (start_ix <= end_ix) {
9
- while (arr[start_ix].t < pivot_val) {
10
- start_ix++;
6
+ const INSERTION_SORT_THRESHOLD = 10;
7
+ function partition(arr, low, high) {
8
+ const pivot = arr[Math.floor((low + high) / 2)][0];
9
+ let i = low;
10
+ let j = high;
11
+ while (i <= j) {
12
+ while (arr[i][0] < pivot) {
13
+ i++;
11
14
  }
12
- while (arr[end_ix].t > pivot_val) {
13
- end_ix--;
15
+ while (arr[j][0] > pivot) {
16
+ j--;
14
17
  }
15
- if (start_ix <= end_ix) {
16
- const temp = arr[start_ix];
17
- arr[start_ix] = arr[end_ix];
18
- arr[end_ix] = temp;
19
- start_ix++;
20
- end_ix--;
18
+ if (i <= j) {
19
+ [arr[i], arr[j]] = [arr[j], arr[i]];
20
+ i++;
21
+ j--;
21
22
  }
22
23
  }
23
- return start_ix;
24
+ return i;
24
25
  }
25
- function quickSort(arr, start_ix = 0, end_ix = arr.length - 1) {
26
- if (start_ix < end_ix) {
27
- const ix = partition(arr, start_ix, end_ix);
28
- quickSort(arr, start_ix, ix - 1);
29
- quickSort(arr, ix, end_ix);
26
+ function quickSort(arr) {
27
+ const stack = [{ low: 0, high: arr.length - 1 }];
28
+ while (stack.length) {
29
+ const { low, high } = stack.pop();
30
+ if (high - low <= INSERTION_SORT_THRESHOLD) {
31
+ for (let i = low + 1; i <= high; i++) {
32
+ const key = arr[i];
33
+ let j = i - 1;
34
+ while (j >= low && arr[j][0] > key[0]) {
35
+ arr[j + 1] = arr[j];
36
+ j--;
37
+ }
38
+ arr[j + 1] = key;
39
+ }
40
+ }
41
+ else {
42
+ const p = partition(arr, low, high);
43
+ if (p - 1 > low)
44
+ stack.push({ low, high: p - 1 });
45
+ if (p < high)
46
+ stack.push({ low: p, high });
47
+ }
30
48
  }
31
49
  return arr;
32
50
  }
33
51
  function sort(arr, by, dir = 'asc', opts) {
34
52
  if (!Array.isArray(arr) || !arr.length)
35
53
  return [];
36
- if (dir !== 'asc' && dir !== 'desc')
37
- throw new Error('Direction should be either asc or desc');
38
- let NOKEY_HIDE = false;
39
- let NOKEY_AT_END = true;
54
+ const NOKEY_HIDE = opts?.nokey_hide === true;
55
+ const NOKEY_AT_END = opts?.nokey_atend !== false;
40
56
  let FILTER_FN = isNotEmpty_1.isNotEmptyObject;
41
- if (opts && Object.prototype.toString.call(opts) === '[object Object]') {
42
- if (opts.nokey_hide === true)
43
- NOKEY_HIDE = true;
44
- if (opts.nokey_atend === false)
45
- NOKEY_AT_END = false;
46
- if (typeof opts.filter_fn === 'function') {
47
- const fn = opts.filter_fn;
48
- FILTER_FN = (el => (0, isNotEmpty_1.isNotEmptyObject)(el) && fn(el));
49
- }
57
+ if (typeof opts?.filter_fn === 'function') {
58
+ const fn = opts.filter_fn;
59
+ FILTER_FN = (el => (0, isNotEmpty_1.isNotEmptyObject)(el) && fn(el));
50
60
  }
51
- const prepared_arr = [];
52
- const nokey_arr = [];
61
+ let getKey;
53
62
  if (typeof by === 'string') {
54
63
  const by_s = by.trim();
55
64
  if (!by_s.length)
56
65
  throw new Error('Sort by as string should contain content');
57
- for (let i = 0; i < arr.length; i++) {
58
- const el = arr[i];
59
- if (!FILTER_FN(el))
60
- continue;
61
- if (el?.[by_s] === undefined) {
62
- nokey_arr.push(el);
63
- }
64
- else {
65
- prepared_arr.push({ t: el[by_s], el });
66
- }
67
- }
66
+ getKey = (el) => el[by_s];
68
67
  }
69
68
  else if (typeof by === 'function') {
70
- let key;
71
- for (let i = 0; i < arr.length; i++) {
72
- const el = arr[i];
73
- if (!FILTER_FN(el))
74
- continue;
75
- key = by(el);
76
- if (key === undefined) {
77
- nokey_arr.push(el);
78
- }
79
- else {
80
- prepared_arr.push({ t: key, el });
81
- }
82
- }
69
+ getKey = by;
83
70
  }
84
71
  else {
85
72
  throw new Error('Sort by should either be a string with content or a function');
86
73
  }
74
+ const prepared_arr = [];
75
+ const nokey_arr = [];
76
+ for (let i = 0; i < arr.length; i++) {
77
+ const el = arr[i];
78
+ if (!FILTER_FN(el))
79
+ continue;
80
+ const key = getKey(el);
81
+ if (key === undefined) {
82
+ nokey_arr.push(el);
83
+ }
84
+ else {
85
+ prepared_arr.push([key, el]);
86
+ }
87
+ }
87
88
  quickSort(prepared_arr);
88
89
  if (dir === 'desc')
89
90
  prepared_arr.reverse();
90
91
  const rslt = [];
91
- if (!NOKEY_HIDE && !NOKEY_AT_END) {
92
- for (let i = 0; i < nokey_arr.length; i++)
93
- rslt.push(nokey_arr[i]);
94
- }
92
+ if (!NOKEY_HIDE && !NOKEY_AT_END)
93
+ rslt.push(...nokey_arr);
95
94
  for (let i = 0; i < prepared_arr.length; i++)
96
- rslt.push(prepared_arr[i].el);
97
- if (!NOKEY_HIDE && NOKEY_AT_END) {
98
- for (let i = 0; i < nokey_arr.length; i++)
99
- rslt.push(nokey_arr[i]);
100
- }
95
+ rslt.push(prepared_arr[i][1]);
96
+ if (!NOKEY_HIDE && NOKEY_AT_END)
97
+ rslt.push(...nokey_arr);
101
98
  return rslt;
102
99
  }
package/date/format.js CHANGED
@@ -36,7 +36,7 @@ function toZone(date, zone) {
36
36
  throw new Error(`format: Invalid zone passed - ${zone}`);
37
37
  const offset = zone_time - client_time;
38
38
  zone_offset_cache.set(ckey, offset);
39
- return new Date(date.getTime() + offset);
39
+ return new Date(client_time + offset);
40
40
  }
41
41
  function runIntl(loc, token, props, val) {
42
42
  const hash = `${loc}:${token}`;
@@ -74,6 +74,10 @@ const Tokens = [
74
74
  ['SSS', d => `${d.getMilliseconds()}`.padStart(3, '0')],
75
75
  ['A', d => d.getHours() < 12 ? 'AM' : 'PM'],
76
76
  ['a', d => d.getHours() < 12 ? 'am' : 'pm'],
77
+ ['l', (d, loc) => runIntl(loc, 'l', { dateStyle: 'short' }, d)],
78
+ ['L', (d, loc) => runIntl(loc, 'L', { dateStyle: 'medium' }, d)],
79
+ ['t', (d, loc) => runIntl(loc, 't', { timeStyle: 'short' }, d)],
80
+ ['T', (d, loc) => runIntl(loc, 'T', { timeStyle: 'medium' }, d)],
77
81
  ]
78
82
  .sort((a, b) => a[0].length > b[0].length ? -1 : 1)
79
83
  .map((el) => [el[0], new RegExp(el[0], 'g'), el[1]]);
package/package.json CHANGED
@@ -1 +1 @@
1
- { "name": "@valkyriestudios/utils", "version": "12.12.0", "description": "A collection of single-function utilities for common tasks", "author": { "name": "Peter Vermeulen", "url": "https://www.linkedin.com/in/petervermeulen1/" }, "keywords": [ "utility", "library", "javascript", "js", "node", "bun" ], "license": "MIT", "repository": { "type": "git", "url": "git+https://github.com/ValkyrieStudios/utils.git" }, "bugs": { "url": "https://github.com/ValkyrieStudios/utils/issues" }, "homepage": "https://github.com/ValkyrieStudios/utils#readme", "types": "index.d.ts" }
1
+ { "name": "@valkyriestudios/utils", "version": "12.13.0", "description": "A collection of single-function utilities for common tasks", "author": { "name": "Peter Vermeulen", "url": "https://www.linkedin.com/in/petervermeulen1/" }, "keywords": [ "utility", "library", "javascript", "js", "node", "bun" ], "license": "MIT", "repository": { "type": "git", "url": "git+https://github.com/ValkyrieStudios/utils.git" }, "bugs": { "url": "https://github.com/ValkyrieStudios/utils/issues" }, "homepage": "https://github.com/ValkyrieStudios/utils#readme", "types": "index.d.ts" }