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