@ezez/utils 1.7.0 → 1.8.1

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 (134) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +1 -0
  3. package/dist/formatDate.d.ts +3 -0
  4. package/dist/formatDate.d.ts.map +1 -0
  5. package/dist/formatDate.js +55 -0
  6. package/dist/formatDate.js.map +1 -0
  7. package/dist/getMultiple.js.map +1 -1
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +1 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/isNumericString.js.map +1 -1
  13. package/dist/mapAsync.js.map +1 -1
  14. package/dist/mostFrequent.d.ts.map +1 -1
  15. package/dist/mostFrequent.js.map +1 -1
  16. package/dist/pull.js.map +1 -1
  17. package/dist/remove.js.map +1 -1
  18. package/dist/replace.d.ts.map +1 -1
  19. package/dist/replace.js +5 -1
  20. package/dist/replace.js.map +1 -1
  21. package/dist/set.js.map +1 -1
  22. package/dist/setImmutable.js.map +1 -1
  23. package/dist/throttle.js.map +1 -1
  24. package/docs/assets/search.js +1 -1
  25. package/docs/functions/cap.html +6 -5
  26. package/docs/functions/capitalize.html +6 -5
  27. package/docs/functions/coalesce.html +6 -5
  28. package/docs/functions/compareArrays.html +6 -5
  29. package/docs/functions/compareProps.html +6 -5
  30. package/docs/functions/ensureArray.html +6 -5
  31. package/docs/functions/ensureDate.html +6 -5
  32. package/docs/functions/ensureError.html +6 -5
  33. package/docs/functions/ensurePrefix.html +6 -5
  34. package/docs/functions/ensureSuffix.html +6 -5
  35. package/docs/functions/ensureTimestamp.html +6 -5
  36. package/docs/functions/escapeRegExp.html +6 -5
  37. package/docs/functions/formatDate.html +136 -0
  38. package/docs/functions/get.html +6 -5
  39. package/docs/functions/getMultiple.html +6 -5
  40. package/docs/functions/insertSeparator.html +6 -5
  41. package/docs/functions/isEmpty.html +6 -5
  42. package/docs/functions/isNumericString.html +6 -5
  43. package/docs/functions/isPlainObject.html +6 -5
  44. package/docs/functions/last.html +6 -5
  45. package/docs/functions/later-1.html +6 -5
  46. package/docs/functions/mapAsync.html +6 -5
  47. package/docs/functions/mapValues.html +6 -5
  48. package/docs/functions/match.html +6 -5
  49. package/docs/functions/merge.html +14 -13
  50. package/docs/functions/mostFrequent.html +6 -5
  51. package/docs/functions/noop.html +6 -5
  52. package/docs/functions/occurrences.html +6 -5
  53. package/docs/functions/omit.html +6 -5
  54. package/docs/functions/pick.html +6 -5
  55. package/docs/functions/pull.html +6 -5
  56. package/docs/functions/remove.html +6 -5
  57. package/docs/functions/replace.html +6 -5
  58. package/docs/functions/rethrow.html +6 -5
  59. package/docs/functions/safe.html +7 -6
  60. package/docs/functions/scale.html +6 -5
  61. package/docs/functions/seq.html +6 -5
  62. package/docs/functions/seqEarlyBreak.html +6 -5
  63. package/docs/functions/set.html +6 -5
  64. package/docs/functions/setImmutable.html +6 -5
  65. package/docs/functions/sortBy.html +6 -5
  66. package/docs/functions/sortProps.html +6 -5
  67. package/docs/functions/stripPrefix.html +6 -5
  68. package/docs/functions/stripSuffix.html +6 -5
  69. package/docs/functions/throttle.html +6 -5
  70. package/docs/functions/truthy.html +6 -5
  71. package/docs/functions/unique.html +6 -5
  72. package/docs/functions/wait.html +6 -5
  73. package/docs/functions/waitFor.html +6 -5
  74. package/docs/functions/waitSync.html +6 -5
  75. package/docs/index.html +6 -4
  76. package/docs/interfaces/ComparePropsOptions.html +6 -6
  77. package/docs/interfaces/GetMultipleSource.html +6 -5
  78. package/docs/interfaces/GetSource.html +6 -5
  79. package/docs/interfaces/IsNumericStringOptions.html +9 -9
  80. package/docs/interfaces/OccurencesOptions.html +6 -6
  81. package/docs/interfaces/SetImmutableSource.html +6 -5
  82. package/docs/interfaces/SetSource.html +6 -5
  83. package/docs/interfaces/ThrottleOptions.html +7 -7
  84. package/docs/interfaces/ThrottledFunctionExtras.html +7 -7
  85. package/docs/modules.html +6 -4
  86. package/docs/pages/CHANGELOG.html +83 -53
  87. package/docs/pages/Introduction.html +5 -4
  88. package/docs/types/Later.html +6 -5
  89. package/docs/types/MapValuesFn.html +6 -5
  90. package/docs/types/MatchCallback.html +6 -5
  91. package/docs/types/SeqEarlyBreaker.html +6 -5
  92. package/docs/types/SeqFn.html +6 -5
  93. package/docs/types/SeqFunctions.html +6 -5
  94. package/docs/types/SetImmutablePath.html +6 -5
  95. package/docs/types/ThrottledFunction.html +6 -5
  96. package/docs/variables/mapValuesUNSET.html +6 -5
  97. package/docs/variables/mergeUNSET.html +6 -5
  98. package/esm/formatDate.d.ts +3 -0
  99. package/esm/formatDate.d.ts.map +1 -0
  100. package/esm/formatDate.js +52 -0
  101. package/esm/formatDate.js.map +1 -0
  102. package/esm/getMultiple.js.map +1 -1
  103. package/esm/index.d.ts +1 -0
  104. package/esm/index.d.ts.map +1 -1
  105. package/esm/index.js +1 -0
  106. package/esm/index.js.map +1 -1
  107. package/esm/isNumericString.js.map +1 -1
  108. package/esm/mapAsync.js.map +1 -1
  109. package/esm/mostFrequent.d.ts.map +1 -1
  110. package/esm/mostFrequent.js.map +1 -1
  111. package/esm/pull.js.map +1 -1
  112. package/esm/remove.js.map +1 -1
  113. package/esm/replace.d.ts.map +1 -1
  114. package/esm/replace.js +5 -1
  115. package/esm/replace.js.map +1 -1
  116. package/esm/set.js.map +1 -1
  117. package/esm/setImmutable.js.map +1 -1
  118. package/esm/throttle.js.map +1 -1
  119. package/package.json +10 -9
  120. package/src/formatDate.spec.ts +199 -0
  121. package/src/formatDate.ts +73 -0
  122. package/src/getMultiple.ts +1 -1
  123. package/src/index.ts +1 -0
  124. package/src/isNumericString.ts +1 -1
  125. package/src/mapAsync.ts +1 -1
  126. package/src/mostFrequent.ts +1 -0
  127. package/src/pull.ts +1 -1
  128. package/src/remove.ts +2 -2
  129. package/src/replace.spec.ts +4 -0
  130. package/src/replace.ts +6 -2
  131. package/src/safe.spec.ts +0 -1
  132. package/src/set.ts +1 -1
  133. package/src/setImmutable.ts +1 -1
  134. package/src/throttle.ts +1 -1
@@ -0,0 +1,73 @@
1
+ /* eslint-disable @typescript-eslint/no-magic-numbers */
2
+ import { ensureDate } from "./ensureDate.js";
3
+
4
+ /**
5
+ * PHP's `strftime`-like date formatter.
6
+ * IMPORTANT: Use Intl.DateTimeFormat everywhere possible. Use this only if you are 100% sure you want to have given
7
+ * date format, not depending on any locale standards.
8
+ *
9
+ * Important: this is work in progress. All locale-based values are not supported yet. Formats that heavily depend on
10
+ * locale won't ever be supported.
11
+ */
12
+ const formatDate = (date: Date | number, format: string, locale = "en-US"): string => { // eslint-disable-line max-lines-per-function, max-len
13
+ const d = ensureDate(date);
14
+ return format.replace(/%([%a-zA-Z])/g, (_, c) => {
15
+ switch (c) {
16
+ case "%": return "%";
17
+ // Day
18
+ case "a": throw new Error("`%a` is not supported yet");
19
+ case "A": throw new Error("`%A` is not supported yet");
20
+ case "d": return String(d.getDate()).padStart(2, "0");
21
+ case "e": return String(d.getDate()).padStart(2, " ");
22
+ case "j": return String(
23
+ Math.floor((d.getTime() - new Date(d.getFullYear(), 0, 0).getTime()) / 86400000),
24
+ ).padStart(3, "0");
25
+ case "u": return String(d.getDay() || 7);
26
+ case "w": return String(d.getDay());
27
+ // Week
28
+ case "U": throw new Error("`%U` is not supported yet");
29
+ case "V": throw new Error("`%V` is not supported yet");
30
+ case "W": throw new Error("`%W` is not supported yet");
31
+ // Month
32
+ case "b": throw new Error("`%b` is not supported yet");
33
+ case "B": throw new Error("`%B` is not supported yet");
34
+ case "h": throw new Error("`%h` is not supported yet");
35
+ case "m": return String(d.getMonth() + 1).padStart(2, "0");
36
+ // Year
37
+ case "C": throw new Error("`%C` is not supported yet");
38
+ case "g": throw new Error("`%g` is not supported yet");
39
+ case "G": throw new Error("`%G` is not supported yet");
40
+ case "y": return String(d.getFullYear()).substring(2);
41
+ case "Y": return String(d.getFullYear());
42
+ // Time
43
+ case "H": return String(d.getHours()).padStart(2, "0");
44
+ case "k": return String(d.getHours()).padStart(2, " ");
45
+ case "I": return String(d.getHours() % 12 || 12).padStart(2, "0");
46
+ case "l": return String(d.getHours() % 12 || 12).padStart(2, " ");
47
+ case "M": return String(d.getMinutes()).padStart(2, "0");
48
+ case "p": return d.getHours() >= 12 ? "PM" : "AM";
49
+ case "P": return d.getHours() >= 12 ? "pm" : "am";
50
+ case "r": return formatDate(d, "%I:%M:%S %p", locale);
51
+ case "R": return formatDate(d, "%H:%M", locale);
52
+ case "S": return String(d.getSeconds()).padStart(2, "0");
53
+ case "T": return formatDate(d, "%H:%M:%S", locale);
54
+ case "X": throw new Error("`%X` is not supported and it will never be, use Intl.DateTimeFormat instead");
55
+ case "z": throw new Error("`%z` is not supported yet");
56
+ case "Z": throw new Error("`%Z` is not supported yet");
57
+ // Time and Date stamps
58
+ case "c": throw new Error("`%c` is not supported and it will never be, use Intl.DateTimeFormat instead");
59
+ case "D": throw new Error("`%D` is not supported and it will never be, use Intl.DateTimeFormat instead");
60
+ case "x": throw new Error("`%x` is not supported and it will never be, use Intl.DateTimeFormat instead");
61
+ case "F": return formatDate(d, "%Y-%m-%d", locale);
62
+ case "s": return String(Math.floor(d.getTime() / 1000));
63
+ // Misc
64
+ case "n": return "\n";
65
+ case "t": return "\t";
66
+ }
67
+ return c as string;
68
+ });
69
+ };
70
+
71
+ export {
72
+ formatDate,
73
+ };
@@ -31,7 +31,7 @@ const DEFAULT = {};
31
31
  const getMultiple = (source: Source, defaultValue: unknown, ...paths: (string | string[])[]): unknown => {
32
32
  const length = paths.length;
33
33
  for (let i = 0; i < length; i++) {
34
- const properties = paths[i];
34
+ const properties = paths[i]!;
35
35
  const result = get(source, properties, DEFAULT);
36
36
  if (result !== DEFAULT) {
37
37
  return result;
package/src/index.ts CHANGED
@@ -11,6 +11,7 @@ export * from "./ensureDate.js";
11
11
  export * from "./ensureError.js";
12
12
  export * from "./ensureTimestamp.js";
13
13
  export * from "./escapeRegExp.js";
14
+ export * from "./formatDate.js";
14
15
  export * from "./get.js";
15
16
  export * from "./getMultiple.js";
16
17
  export * from "./insertSeparator.js";
@@ -42,7 +42,7 @@ const isNumericString = (string: string, options: Options = {}) => { // eslint-d
42
42
  return false;
43
43
  }
44
44
 
45
- const expParts = parts[parts.length - 1].split("e");
45
+ const expParts = parts[parts.length - 1]!.split("e");
46
46
 
47
47
  if (!options.allowExponents) {
48
48
  if (expParts.length > 1) {
package/src/mapAsync.ts CHANGED
@@ -24,7 +24,7 @@ const mapAsync = async <T, Y>(
24
24
  const l = context.length;
25
25
 
26
26
  for (let i = 0; i < l; i++) {
27
- const item = context[i];
27
+ const item = context[i]!;
28
28
  // eslint-disable-next-line callback-return
29
29
  result.push(callback(item, i, context));
30
30
  if (Date.now() - lastWaitMoment >= pauseEvery) {
@@ -19,6 +19,7 @@ const mostFrequent = <T>(array: T[]): T => {
19
19
  }
20
20
  });
21
21
 
22
+ // @ts-expect-error - idk if there is a good workaround for this with `noUncheckedIndexedAccess`
22
23
  return topValue;
23
24
  };
24
25
 
package/src/pull.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  const pull = <T>(array: T[], ...valuesToPull: T[]): T[] => {
7
7
  const len = array.length;
8
8
  for (let i = len - 1; i >= 0; i--) {
9
- if (valuesToPull.includes(array[i])) {
9
+ if (valuesToPull.includes(array[i]!)) {
10
10
  array.splice(i, 1);
11
11
  }
12
12
  }
package/src/remove.ts CHANGED
@@ -12,9 +12,9 @@ const remove = <T>(array: T[], fn: (elem: T, num: number, list: T[]) => boolean)
12
12
  const removedValues = [];
13
13
 
14
14
  for (let counter = 0; counter < len; counter++) {
15
- if (fn(array[counter], counter, array)) {
15
+ if (fn(array[counter]!, counter, array)) {
16
16
  idsToRemove.push(counter - idsToRemove.length);
17
- removedValues.push(array[counter]);
17
+ removedValues.push(array[counter]!);
18
18
  }
19
19
  }
20
20
 
@@ -19,4 +19,8 @@ describe("replace", () => {
19
19
  it("doesn't break on regexp characters", () => {
20
20
  replace("Hello.", { ".": "!" }).must.equal("Hello!");
21
21
  });
22
+
23
+ it("replaces nothing when empty object given", async () => {
24
+ replace("Hello.", {}).must.equal("Hello.");
25
+ });
22
26
  });
package/src/replace.ts CHANGED
@@ -9,9 +9,13 @@ import { escapeRegExp } from "./escapeRegExp.js";
9
9
  * @example replace("Hello, %name%! Nice to meet you %name%!", { "%name%": "Jane" }) // "Hello, Jane! Nice to meet you Jane!"
10
10
  */
11
11
  const replace = (source: string, replaceMap: Record<string, string>) => {
12
+ const keys = Object.keys(replaceMap);
13
+ if (keys.length === 0) {
14
+ return source;
15
+ }
12
16
  /* eslint-enable max-len */
13
- const regex = new RegExp(Object.keys(replaceMap).map(escapeRegExp).join("|"), "g");
14
- return source.replace(regex, (matched) => replaceMap[matched]);
17
+ const regex = new RegExp(keys.map(escapeRegExp).join("|"), "g");
18
+ return source.replace(regex, (matched) => replaceMap[matched]!);
15
19
  };
16
20
 
17
21
  export {
package/src/safe.spec.ts CHANGED
@@ -40,7 +40,6 @@ describe("safe", () => {
40
40
  });
41
41
 
42
42
  it("doesn't 'work' with promises", () => {
43
- // eslint-disable-next-line @typescript-eslint/require-await
44
43
  const result = safe(async () => {
45
44
  throw new Error("Boo!!!");
46
45
  });
package/src/set.ts CHANGED
@@ -39,7 +39,7 @@ const set = (source: Source, path: string | string[], value: unknown): Source |
39
39
  let current: Source | unknown = result;
40
40
  for (let i = 0; i < len; i++) {
41
41
  const isLast = i === len - 1;
42
- const key = pathParts[i];
42
+ const key = pathParts[i]!;
43
43
  if (isLast) {
44
44
  (current as Source)[key] = value;
45
45
  return result;
@@ -80,7 +80,7 @@ const setImmutable = (source: Source, path: Path, value: unknown): Source | unkn
80
80
  let current: Source | unknown = result;
81
81
  for (let i = 0; i < len; i++) {
82
82
  const isLast = i === len - 1;
83
- const key = pathParts[i];
83
+ const key = pathParts[i]!;
84
84
  if (isLast) {
85
85
  (current as Source)[key] = value;
86
86
  return result;
package/src/throttle.ts CHANGED
@@ -61,7 +61,7 @@ const throttle = <RT, F extends (...args: any[]) => RT>( // eslint-disable-line
61
61
  throw new TypeError("`time` must be an array with at least one number.");
62
62
  }
63
63
 
64
- const finalTime = typeof time === "number" ? time : time[time.length - 1];
64
+ const finalTime = typeof time === "number" ? time : time[time.length - 1]!;
65
65
 
66
66
  let lastRun = 0,
67
67
  timeoutId: ReturnType<typeof setTimeout> | null = null,