@ztimson/utils 0.26.26 → 0.27.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.
package/dist/index.mjs CHANGED
@@ -117,44 +117,33 @@ ${opts.message || this.desc}`;
117
117
  `;
118
118
  }
119
119
  }
120
- function applyDeltas(target, deltas) {
121
- for (const delta of deltas) {
122
- for (const [key, value] of Object.entries(delta)) {
123
- if (value === null) {
124
- delete target[key];
125
- } else if (Array.isArray(value)) {
126
- target[key] = [...value];
127
- } else if (typeof value === "object") {
128
- if (typeof target[key] !== "object" || Array.isArray(target[key]) || !target[key])
129
- target[key] = {};
130
- applyDeltas(target[key], [value]);
131
- } else {
132
- target[key] = value;
133
- }
134
- }
120
+ function applyDelta(base, deltas) {
121
+ if (deltas === null) return null;
122
+ if (typeof base !== "object" || base === null) return deltas === void 0 ? base : deltas;
123
+ const result = Array.isArray(base) ? [...base] : { ...base };
124
+ for (const key in deltas) {
125
+ const val = deltas[key];
126
+ if (val === void 0) delete result[key];
127
+ else if (typeof val === "object" && val !== null && !Array.isArray(val)) result[key] = applyDelta(result[key], val);
128
+ else result[key] = val;
135
129
  }
136
- return target;
130
+ return result;
137
131
  }
138
- function calcDelta(old, target) {
132
+ function calcDelta(old, updated) {
133
+ if (updated == null) return null;
139
134
  const delta = {};
140
- const keys = /* @__PURE__ */ new Set([...Object.keys(old || {}), ...Object.keys(target || {})]);
141
- for (const key of keys) {
142
- const val1 = old == null ? void 0 : old[key];
143
- const val2 = target == null ? void 0 : target[key];
144
- if (!(key in target)) {
145
- delta[key] = val1;
146
- } else if (!(key in old)) {
147
- delta[key] = null;
148
- } else if (Array.isArray(val1) || Array.isArray(val2)) {
149
- if (JSON.stringify(val1) !== JSON.stringify(val2)) delta[key] = val1;
150
- } else if (typeof val1 === "object" && typeof val2 === "object" && val1 && val2) {
151
- const nested = calcDelta(val1, val2);
152
- if (Object.keys(nested).length) delta[key] = nested;
153
- } else if (val1 !== val2) {
154
- delta[key] = val1;
135
+ const isObj = (v) => v && typeof v === "object" && !Array.isArray(v);
136
+ for (const key of /* @__PURE__ */ new Set([...old ? Object.keys(old) : [], ...updated ? Object.keys(updated) : []])) {
137
+ const oldVal = old == null ? void 0 : old[key];
138
+ const newVal = updated == null ? void 0 : updated[key];
139
+ if (isObj(oldVal) && isObj(newVal)) {
140
+ const nested = calcDelta(oldVal, newVal);
141
+ if (nested !== null && Object.keys(nested).length > 0) delta[key] = nested;
142
+ } else if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
143
+ delta[key] = newVal;
155
144
  }
156
145
  }
157
- return delta;
146
+ return Object.keys(delta).length === 0 ? {} : delta;
158
147
  }
159
148
  function clean(obj, undefinedOnly = false) {
160
149
  if (obj == null) throw new Error("Cannot clean a NULL value");
@@ -896,6 +885,33 @@ function toCsv(target, flatten = true) {
896
885
  }).join(","))
897
886
  ].join("\n");
898
887
  }
888
+ function dec2Frac(num, maxDen = 1e3) {
889
+ let sign = Math.sign(num);
890
+ num = Math.abs(num);
891
+ if (Number.isInteger(num)) return sign * num + "";
892
+ let closest = { n: 0, d: 1, diff: Math.abs(num) };
893
+ for (let d = 1; d <= maxDen; d++) {
894
+ let n = Math.round(num * d);
895
+ let diff = Math.abs(num - n / d);
896
+ if (diff < closest.diff) {
897
+ closest = { n, d, diff };
898
+ if (diff < 1e-8) break;
899
+ }
900
+ }
901
+ let integer = Math.floor(closest.n / closest.d);
902
+ let numerator = closest.n - integer * closest.d;
903
+ return (sign < 0 ? "-" : "") + (integer ? integer + " " : "") + (numerator ? numerator + "/" + closest.d : "");
904
+ }
905
+ function fracToDec(frac) {
906
+ let split = frac.split(" ");
907
+ const whole = split.length == 2 ? Number(split[0]) : 0;
908
+ split = split.pop().split("/");
909
+ return whole + Number(split[0]) / Number(split[1]);
910
+ }
911
+ function numSuffix(n) {
912
+ const s = ["th", "st", "nd", "rd"], v = n % 100;
913
+ return `${n}${s[(v - 20) % 10] || s[v] || s[0]}`;
914
+ }
899
915
  function adjustedInterval(cb, ms) {
900
916
  let cancel = false, timeout = null;
901
917
  const p = async () => {
@@ -911,103 +927,101 @@ function adjustedInterval(cb, ms) {
911
927
  if (timeout) clearTimeout(timeout);
912
928
  };
913
929
  }
914
- function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(), tz) {
915
- const timezones = [
916
- ["IDLW", -12],
917
- ["SST", -11],
918
- ["HST", -10],
919
- ["AKST", -9],
920
- ["PST", -8],
921
- ["MST", -7],
922
- ["CST", -6],
923
- ["EST", -5],
924
- ["AST", -4],
925
- ["BRT", -3],
926
- ["MAT", -2],
927
- ["AZOT", -1],
928
- ["UTC", 0],
929
- ["CET", 1],
930
- ["EET", 2],
931
- ["MSK", 3],
932
- ["AST", 4],
933
- ["PKT", 5],
934
- ["IST", 5.5],
935
- ["BST", 6],
936
- ["ICT", 7],
937
- ["CST", 8],
938
- ["JST", 9],
939
- ["AEST", 10],
940
- ["SBT", 11],
941
- ["FJT", 12],
942
- ["TOT", 13],
943
- ["LINT", 14]
944
- ];
945
- function adjustTz(date2, gmt) {
946
- const currentOffset = date2.getTimezoneOffset();
947
- const adjustedOffset = gmt * 60;
948
- return new Date(date2.getTime() + (adjustedOffset + currentOffset) * 6e4);
949
- }
950
- function day(num) {
951
- return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][num] || "Unknown";
952
- }
953
- function doy(date2) {
954
- const start = /* @__PURE__ */ new Date(`${date2.getFullYear()}-01-01 0:00:00`);
955
- return Math.ceil((date2.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24));
956
- }
957
- function month(num) {
958
- return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][num] || "Unknown";
959
- }
960
- function suffix(num) {
961
- if (num % 100 >= 11 && num % 100 <= 13) return `${num}th`;
962
- switch (num % 10) {
963
- case 1:
964
- return `${num}st`;
965
- case 2:
966
- return `${num}nd`;
967
- case 3:
968
- return `${num}rd`;
969
- default:
970
- return `${num}th`;
930
+ function dayOfWeek(d) {
931
+ return ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][d];
932
+ }
933
+ function dayOfYear(date) {
934
+ const start = new Date(Date.UTC(date.getUTCFullYear(), 0, 1));
935
+ return Math.ceil((date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24));
936
+ }
937
+ function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(), tz = "local") {
938
+ var _a;
939
+ if (typeof date === "number" || typeof date === "string") date = new Date(date);
940
+ if (isNaN(date.getTime())) throw new Error("Invalid date input");
941
+ const numericTz = typeof tz === "number";
942
+ const localTz = tz === "local" || !numericTz && ((_a = tz.toLowerCase) == null ? void 0 : _a.call(tz)) === "local";
943
+ const tzName = localTz ? Intl.DateTimeFormat().resolvedOptions().timeZone : numericTz ? "UTC" : tz;
944
+ if (!numericTz && tzName !== "UTC") {
945
+ try {
946
+ new Intl.DateTimeFormat("en-US", { timeZone: tzName }).format();
947
+ } catch {
948
+ throw new Error(`Invalid timezone: ${tzName}`);
949
+ }
950
+ }
951
+ let zonedDate = new Date(date);
952
+ if (!numericTz && tzName !== "UTC") {
953
+ const parts = new Intl.DateTimeFormat("en-US", {
954
+ timeZone: tzName,
955
+ year: "numeric",
956
+ month: "2-digit",
957
+ day: "2-digit",
958
+ hour: "2-digit",
959
+ minute: "2-digit",
960
+ second: "2-digit",
961
+ hour12: false
962
+ }).formatToParts(date);
963
+ const get2 = (type) => {
964
+ var _a2;
965
+ return (_a2 = parts.find((p) => p.type === type)) == null ? void 0 : _a2.value;
966
+ };
967
+ const build = `${get2("year")}-${get2("month")}-${get2("day")}T${get2("hour")}:${get2("minute")}:${get2("second")}Z`;
968
+ zonedDate = new Date(build);
969
+ } else if (numericTz || tzName === "UTC") {
970
+ const offset = numericTz ? tz : 0;
971
+ zonedDate = new Date(date.getTime() + offset * 60 * 60 * 1e3);
972
+ }
973
+ const get = (fn2) => numericTz || tzName === "UTC" ? zonedDate[`getUTC${fn2}`]() : zonedDate[`get${fn2}`]();
974
+ function getTZOffset() {
975
+ var _a2, _b;
976
+ if (numericTz) {
977
+ const total = tz * 60;
978
+ const hours = Math.floor(Math.abs(total) / 60);
979
+ const mins = Math.abs(total) % 60;
980
+ return `${tz >= 0 ? "+" : "-"}${String(hours).padStart(2, "0")}:${String(mins).padStart(2, "0")}`;
981
+ }
982
+ try {
983
+ const offset = (_b = (_a2 = new Intl.DateTimeFormat("en-US", { timeZone: tzName, timeZoneName: "longOffset", hour: "2-digit", minute: "2-digit" }).formatToParts(date).find((p) => p.type === "timeZoneName")) == null ? void 0 : _a2.value.match(/([+-]\d{2}:\d{2})/)) == null ? void 0 : _b[1];
984
+ if (offset) return offset;
985
+ } catch {
986
+ }
987
+ return "+00:00";
988
+ }
989
+ function getTZAbbr() {
990
+ var _a2;
991
+ if (numericTz && tz === 0) return "UTC";
992
+ try {
993
+ return ((_a2 = new Intl.DateTimeFormat("en-US", { timeZone: tzName, timeZoneName: "short" }).formatToParts(date).find((p) => p.type === "timeZoneName")) == null ? void 0 : _a2.value) || "";
994
+ } catch {
995
+ return tzName;
971
996
  }
972
997
  }
973
- function tzOffset(offset) {
974
- const hours = ~~(offset / 60);
975
- const minutes = offset % 60;
976
- return (offset > 0 ? "-" : "") + `${hours}:${minutes.toString().padStart(2, "0")}`;
977
- }
978
- if (typeof date == "number" || typeof date == "string" || date == null) date = new Date(date);
979
- let t;
980
- if (tz == null) tz = -(date.getTimezoneOffset() / 60);
981
- t = timezones.find((t2) => isNaN(tz) ? t2[0] == tz : t2[1] == tz);
982
- if (!t) throw new Error(`Unknown timezone: ${tz}`);
983
- date = adjustTz(date, t[1]);
984
998
  const tokens = {
985
- "YYYY": date.getFullYear().toString(),
986
- "YY": date.getFullYear().toString().slice(2),
987
- "MMMM": month(date.getMonth()),
988
- "MMM": month(date.getMonth()).slice(0, 3),
989
- "MM": (date.getMonth() + 1).toString().padStart(2, "0"),
990
- "M": (date.getMonth() + 1).toString(),
991
- "DDD": doy(date).toString(),
992
- "DD": date.getDate().toString().padStart(2, "0"),
993
- "Do": suffix(date.getDate()),
994
- "D": date.getDate().toString(),
995
- "dddd": day(date.getDay()),
996
- "ddd": day(date.getDay()).slice(0, 3),
997
- "HH": date.getHours().toString().padStart(2, "0"),
998
- "H": date.getHours().toString(),
999
- "hh": (date.getHours() % 12 || 12).toString().padStart(2, "0"),
1000
- "h": (date.getHours() % 12 || 12).toString(),
1001
- "mm": date.getMinutes().toString().padStart(2, "0"),
1002
- "m": date.getMinutes().toString(),
1003
- "ss": date.getSeconds().toString().padStart(2, "0"),
1004
- "s": date.getSeconds().toString(),
1005
- "SSS": date.getMilliseconds().toString().padStart(3, "0"),
1006
- "A": date.getHours() >= 12 ? "PM" : "AM",
1007
- "a": date.getHours() >= 12 ? "pm" : "am",
1008
- "ZZ": tzOffset(t[1] * 60).replace(":", ""),
1009
- "Z": tzOffset(t[1] * 60),
1010
- "z": typeof tz == "string" ? tz : t[0]
999
+ YYYY: get("FullYear").toString(),
1000
+ YY: get("FullYear").toString().slice(2),
1001
+ MMMM: month(get("Month")),
1002
+ MMM: month(get("Month")).slice(0, 3),
1003
+ MM: (get("Month") + 1).toString().padStart(2, "0"),
1004
+ M: (get("Month") + 1).toString(),
1005
+ DDD: dayOfYear(zonedDate).toString(),
1006
+ DD: get("Date").toString().padStart(2, "0"),
1007
+ Do: numSuffix(get("Date")),
1008
+ D: get("Date").toString(),
1009
+ dddd: dayOfWeek(get("Day")),
1010
+ ddd: dayOfWeek(get("Day")).slice(0, 3),
1011
+ HH: get("Hours").toString().padStart(2, "0"),
1012
+ H: get("Hours").toString(),
1013
+ hh: (get("Hours") % 12 || 12).toString().padStart(2, "0"),
1014
+ h: (get("Hours") % 12 || 12).toString(),
1015
+ mm: get("Minutes").toString().padStart(2, "0"),
1016
+ m: get("Minutes").toString(),
1017
+ ss: get("Seconds").toString().padStart(2, "0"),
1018
+ s: get("Seconds").toString(),
1019
+ SSS: get("Milliseconds").toString().padStart(3, "0"),
1020
+ A: get("Hours") >= 12 ? "PM" : "AM",
1021
+ a: get("Hours") >= 12 ? "pm" : "am",
1022
+ ZZ: getTZOffset().replace(":", ""),
1023
+ Z: getTZOffset(),
1024
+ z: getTZAbbr()
1011
1025
  };
1012
1026
  return format.replace(/YYYY|YY|MMMM|MMM|MM|M|DDD|DD|Do|D|dddd|ddd|HH|H|hh|h|mm|m|ss|s|SSS|A|a|ZZ|Z|z/g, (token) => tokens[token]);
1013
1027
  }
@@ -1015,6 +1029,9 @@ function instantInterval(fn2, interval) {
1015
1029
  fn2();
1016
1030
  return setInterval(fn2, interval);
1017
1031
  }
1032
+ function month(m) {
1033
+ return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][m];
1034
+ }
1018
1035
  function sleep(ms) {
1019
1036
  return new Promise((res) => setTimeout(res, ms));
1020
1037
  }
@@ -1763,29 +1780,6 @@ const _Logger = class _Logger extends TypedEmitter {
1763
1780
  };
1764
1781
  __publicField(_Logger, "LOG_LEVEL", 4);
1765
1782
  let Logger = _Logger;
1766
- function dec2Frac(num, maxDen = 1e3) {
1767
- let sign = Math.sign(num);
1768
- num = Math.abs(num);
1769
- if (Number.isInteger(num)) return sign * num + "";
1770
- let closest = { n: 0, d: 1, diff: Math.abs(num) };
1771
- for (let d = 1; d <= maxDen; d++) {
1772
- let n = Math.round(num * d);
1773
- let diff = Math.abs(num - n / d);
1774
- if (diff < closest.diff) {
1775
- closest = { n, d, diff };
1776
- if (diff < 1e-8) break;
1777
- }
1778
- }
1779
- let integer = Math.floor(closest.n / closest.d);
1780
- let numerator = closest.n - integer * closest.d;
1781
- return (sign < 0 ? "-" : "") + (integer ? integer + " " : "") + (numerator ? numerator + "/" + closest.d : "");
1782
- }
1783
- function fracToDec(frac) {
1784
- let split = frac.split(" ");
1785
- const whole = split.length == 2 ? Number(split[0]) : 0;
1786
- split = split.pop().split("/");
1787
- return whole + Number(split[0]) / Number(split[1]);
1788
- }
1789
1783
  function compareVersions(target, vs) {
1790
1784
  const [tMajor, tMinor, tPatch] = target.split(".").map((v) => +v.replace(/[^0-9]/g, ""));
1791
1785
  const [vMajor, vMinor, vPatch] = vs.split(".").map((v) => +v.replace(/[^0-9]/g, ""));
@@ -2370,7 +2364,7 @@ export {
2370
2364
  UnauthorizedError,
2371
2365
  addUnique,
2372
2366
  adjustedInterval,
2373
- applyDeltas,
2367
+ applyDelta,
2374
2368
  arrayDiff,
2375
2369
  calcDelta,
2376
2370
  camelCase,
@@ -2379,6 +2373,8 @@ export {
2379
2373
  compareVersions,
2380
2374
  contrast,
2381
2375
  createJwt,
2376
+ dayOfWeek,
2377
+ dayOfYear,
2382
2378
  dec2Frac,
2383
2379
  decodeJwt,
2384
2380
  deepCopy,
@@ -2415,6 +2411,8 @@ export {
2415
2411
  matchAll,
2416
2412
  md5,
2417
2413
  mixin,
2414
+ month,
2415
+ numSuffix,
2418
2416
  pad,
2419
2417
  parseUrl,
2420
2418
  pascalCase,