@manta-eu/lib 0.1.9 → 0.1.10

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 (66) hide show
  1. package/dist/ad-platform-links.js +1 -0
  2. package/dist/ad-platform-links.js.map +1 -0
  3. package/dist/array.js +1 -0
  4. package/dist/array.js.map +1 -0
  5. package/dist/asset-upload-grouping.js +1 -0
  6. package/dist/asset-upload-grouping.js.map +1 -0
  7. package/dist/backoff.js +1 -0
  8. package/dist/backoff.js.map +1 -0
  9. package/dist/color.js +1 -0
  10. package/dist/color.js.map +1 -0
  11. package/dist/connection-string.js +1 -0
  12. package/dist/connection-string.js.map +1 -0
  13. package/dist/countries.js +1 -0
  14. package/dist/countries.js.map +1 -0
  15. package/dist/date.js +1 -0
  16. package/dist/date.js.map +1 -0
  17. package/dist/enum.js +1 -0
  18. package/dist/enum.js.map +1 -0
  19. package/dist/external-app.d.ts +3 -0
  20. package/dist/external-app.d.ts.map +1 -0
  21. package/dist/external-app.js +29 -0
  22. package/dist/external-app.js.map +1 -0
  23. package/dist/file.js +1 -0
  24. package/dist/file.js.map +1 -0
  25. package/dist/humanize.js +1 -0
  26. package/dist/humanize.js.map +1 -0
  27. package/dist/identifier-words.js +1 -0
  28. package/dist/identifier-words.js.map +1 -0
  29. package/dist/number.js +1 -0
  30. package/dist/number.js.map +1 -0
  31. package/dist/object-url.js +1 -0
  32. package/dist/object-url.js.map +1 -0
  33. package/dist/present.js +1 -0
  34. package/dist/present.js.map +1 -0
  35. package/dist/set.js +1 -0
  36. package/dist/set.js.map +1 -0
  37. package/dist/sleep.js +1 -0
  38. package/dist/sleep.js.map +1 -0
  39. package/dist/string.js +1 -0
  40. package/dist/string.js.map +1 -0
  41. package/dist/types.js +1 -0
  42. package/dist/types.js.map +1 -0
  43. package/dist/url.js +1 -0
  44. package/dist/url.js.map +1 -0
  45. package/package.json +7 -2
  46. package/src/ad-platform-links.ts +20 -0
  47. package/src/array.ts +9 -0
  48. package/src/asset-upload-grouping.ts +70 -0
  49. package/src/backoff.ts +14 -0
  50. package/src/color.ts +92 -0
  51. package/src/connection-string.ts +95 -0
  52. package/src/countries.ts +18 -0
  53. package/src/date.ts +51 -0
  54. package/src/enum.ts +18 -0
  55. package/src/external-app.ts +27 -0
  56. package/src/file.ts +19 -0
  57. package/src/humanize.ts +94 -0
  58. package/src/identifier-words.ts +16 -0
  59. package/src/number.ts +10 -0
  60. package/src/object-url.ts +10 -0
  61. package/src/present.ts +30 -0
  62. package/src/set.ts +38 -0
  63. package/src/sleep.ts +3 -0
  64. package/src/string.ts +18 -0
  65. package/src/types.ts +1 -0
  66. package/src/url.ts +47 -0
@@ -11,3 +11,4 @@ export function generateMetaAdsManagerCampaignLink(args) {
11
11
  url.searchParams.set("filter_set", filterSet);
12
12
  return url.toString();
13
13
  }
14
+ //# sourceMappingURL=ad-platform-links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ad-platform-links.js","sourceRoot":"","sources":["../src/ad-platform-links.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,kCAAkC,CAAC,IAAuC;IACxF,MAAM,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC;IAC5E,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxE,MAAM,SAAS,GAAG,0CAA0C,eAAe,MAAM,eAAe,IAAI,WAAW,GAAG,CAAC;IACnH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,6DAA6D,CAAC,CAAC;IACnF,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC;IACjD,IAAI,iBAAiB,EAAE,CAAC;QACtB,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;IACzD,CAAC;IACD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IAC9C,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC"}
package/dist/array.js CHANGED
@@ -5,3 +5,4 @@ export function arrayWrap(value) {
5
5
  export function replaceAtIndex(arr, index, item) {
6
6
  return update(index, item, arr);
7
7
  }
8
+ //# sourceMappingURL=array.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array.js","sourceRoot":"","sources":["../src/array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE/B,MAAM,UAAU,SAAS,CAAI,KAAc;IACzC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,cAAc,CAAI,GAAQ,EAAE,KAAa,EAAE,IAAO;IAChE,OAAO,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC"}
@@ -31,3 +31,4 @@ export function groupUploadedAssetsByBaseName(props) {
31
31
  unmatched,
32
32
  };
33
33
  }
34
+ //# sourceMappingURL=asset-upload-grouping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-upload-grouping.js","sourceRoot":"","sources":["../src/asset-upload-grouping.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,+BAA+B,CAC7C,KAAmD;IAEnD,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACtC,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAE1F,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,aAAa,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,SAAS;QACtC,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7D,OAAO,EAAE,QAAQ,EAAE,QAAQ,IAAI,cAAc,EAAE,KAAK,EAAE,CAAC;IACzD,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,cAAc,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAC/D,CAAC;AAiBD,MAAM,UAAU,6BAA6B,CAC3C,KAAyD;IAKzD,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAC1B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA8C,CAAC;IACvE,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAChE,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC7E,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAChE,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO;QACL,MAAM,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9B,SAAS;KACV,CAAC;AACJ,CAAC"}
package/dist/backoff.js CHANGED
@@ -4,3 +4,4 @@ export function backoffDelayMs(attempt, backoff, random = Math.random) {
4
4
  const jitter = random() * exponential * jitterRatio;
5
5
  return Math.min(maxMs, exponential + jitter);
6
6
  }
7
+ //# sourceMappingURL=backoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backoff.js","sourceRoot":"","sources":["../src/backoff.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,OAAgB,EAAE,SAAuB,IAAI,CAAC,MAAM;IAClG,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,WAAW,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IAClE,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,EAAE,GAAG,WAAW,GAAG,WAAW,CAAC;IACpD,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAAC,CAAC;AAC/C,CAAC"}
package/dist/color.js CHANGED
@@ -59,3 +59,4 @@ export function getAgeColor(date) {
59
59
  const hue = Math.round(120 - clampedHours * 3.3333);
60
60
  return `hsl(${hue}, 80%, 40%)`;
61
61
  }
62
+ //# sourceMappingURL=color.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color.js","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"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"}
@@ -69,3 +69,4 @@ function propertyEntries(text) {
69
69
  .map(([, name = "", value = ""]) => [name.trim(), value.trim()])
70
70
  .filter(([name]) => isPresent(name));
71
71
  }
72
+ //# sourceMappingURL=connection-string.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-string.js","sourceRoot":"","sources":["../src/connection-string.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAiBtC,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,UAAwB,EAAE;IAC7E,MAAM,EAAE,mBAAmB,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAChD,MAAM,aAAa,GAAG,WAAW,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACjE,IAAI,CAAC,aAAa;QAAE,OAAO,SAAS,CAAC;IAErC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC;IACvC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC9E,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAE1C,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,mBAAmB,CAAC,CAAC;QACnF,OAAO;YACL,MAAM;YACN,GAAG,kBAAkB,CAAC,SAAS,CAAC;YAChC,IAAI;YACJ,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,KAAK,EAAE,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC;SACvE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzC,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,OAAO,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,aAAa,GAAG,4BAA4B,CAAC;AAEnD,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IAClC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;AAC/E,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,GAAG,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnD,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,4FAA4F;AAC5F,SAAS,SAAS,CAAC,MAAc,EAAE,IAAY,EAAE,mBAA4B;IAC3E,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACtG,OAAO,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,QAAQ,CAAC,MAAc,EAAE,IAAY;IAC5C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IAE3C,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC;QAC9C,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,QAAQ,EAAE,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1C,QAAQ,EAAE,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1C,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC;QACrE,KAAK,EAAE,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC;KAC7B,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,OAA+B;IACzD,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED,MAAM,YAAY,GAAG,UAAU,CAAC;AAChC,mGAAmG;AACnG,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAA,oBAAoB,CAAC;AACnD,MAAM,UAAU,GAAG,OAAO,CAAC;AAC3B,MAAM,eAAe,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAA,GAAG,YAAY,QAAQ,WAAW,IAAI,UAAU,GAAG,EAAE,GAAG,CAAC,CAAC;AAEvG,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;SACvC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,CAAC,EAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;SACjF,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AACzC,CAAC"}
package/dist/countries.js CHANGED
@@ -16,3 +16,4 @@ export function getLanguageName(languageCode) {
16
16
  return languageCode;
17
17
  }
18
18
  }
19
+ //# sourceMappingURL=countries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"countries.js","sourceRoot":"","sources":["../src/countries.ts"],"names":[],"mappings":"AAAA,MAAM,kBAAkB,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC7E,MAAM,oBAAoB,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;AAEjF,MAAM,UAAU,cAAc,CAAC,WAAmB;IAChD,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,WAAW,CAAC;IACrB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,YAAoB;IAClD,IAAI,CAAC;QACH,OAAO,oBAAoB,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,IAAI,YAAY,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,YAAY,CAAC;IACtB,CAAC;AACH,CAAC"}
package/dist/date.js CHANGED
@@ -25,3 +25,4 @@ export function formatTime(date, options = {}) {
25
25
  export function formatDateTime(date, formatStr = "yyyy-MM-dd HH:mm", options) {
26
26
  return format(date, formatStr, options);
27
27
  }
28
+ //# sourceMappingURL=date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.js","sourceRoot":"","sources":["../src/date.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAaxC,MAAM,UAAU,OAAO,CACrB,IAAuB,EACvB,UAA2B,EAC3B,UAAmB;IAEnB,IAAI,KAAyB,CAAC;IAC9B,IAAI,OAA2B,CAAC;IAEhC,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,UAAU,CAAC;QACnB,OAAO,GAAG,UAAU,CAAC;IACvB,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAwB;IACjD,OAAO,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAmB;IAC/C,OAAO,SAAS,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;AACrD,CAAC;AAID,MAAM,UAAU,UAAU,CAAC,IAAU,EAAE,UAA6B,EAAE;IACpE,OAAO,IAAI,CAAC,kBAAkB,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAmB,EAAE,SAAS,GAAG,kBAAkB,EAAE,OAAuB;IACzG,OAAO,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC"}
package/dist/enum.js CHANGED
@@ -7,3 +7,4 @@ export function enumToOptions(enums, labelFunction = identity) {
7
7
  }))
8
8
  .sort((a, b) => a.label.localeCompare(b.label));
9
9
  }
10
+ //# sourceMappingURL=enum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enum.js","sourceRoot":"","sources":["../src/enum.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAOjC,MAAM,UAAU,aAAa,CAC3B,KAAU,EACV,gBAAsC,QAAQ;IAE9C,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACf,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC;KAC5B,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const externalAppClientIdPrefix = "ext-";
2
+ export declare function redirectUrlProblem(raw: string): string | undefined;
3
+ //# sourceMappingURL=external-app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-app.d.ts","sourceRoot":"","sources":["../src/external-app.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,SAAS,CAAC;AAMhD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAkBlE"}
@@ -0,0 +1,29 @@
1
+ import { isPresent } from "./present.js";
2
+ export const externalAppClientIdPrefix = "ext-";
3
+ const loopbackHosts = new Set(["localhost", "127.0.0.1", "[::1]"]);
4
+ const maxRedirectUrlLength = 2048;
5
+ // Keycloak compares a redirect URL with what the app sends as an exact string, so it is stored as typed.
6
+ export function redirectUrlProblem(raw) {
7
+ if (raw.length > maxRedirectUrlLength)
8
+ return `Keep it under ${maxRedirectUrlLength} characters`;
9
+ if (raw.includes("*"))
10
+ return "Wildcards are not allowed";
11
+ if (/[\s,]/.test(raw))
12
+ return "Leave out commas and spaces, one URL per field";
13
+ let url;
14
+ try {
15
+ url = new URL(raw);
16
+ }
17
+ catch {
18
+ return "Enter a full URL, like https://app.example.com/callback";
19
+ }
20
+ if (url.protocol !== "https:" && !(url.protocol === "http:" && loopbackHosts.has(url.hostname))) {
21
+ return "Use https, or http for localhost";
22
+ }
23
+ if (isPresent(url.username) || isPresent(url.password))
24
+ return "Leave out the username and password";
25
+ if (isPresent(url.hash))
26
+ return "Leave out the #fragment";
27
+ return undefined;
28
+ }
29
+ //# sourceMappingURL=external-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-app.js","sourceRoot":"","sources":["../src/external-app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEhD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;AACnE,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAElC,yGAAyG;AACzG,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,IAAI,GAAG,CAAC,MAAM,GAAG,oBAAoB;QAAE,OAAO,iBAAiB,oBAAoB,aAAa,CAAC;IACjG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,2BAA2B,CAAC;IAC1D,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,gDAAgD,CAAC;IAE/E,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,yDAAyD,CAAC;IACnE,CAAC;IAED,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QAChG,OAAO,kCAAkC,CAAC;IAC5C,CAAC;IACD,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,qCAAqC,CAAC;IACrG,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,yBAAyB,CAAC;IAC1D,OAAO,SAAS,CAAC;AACnB,CAAC"}
package/dist/file.js CHANGED
@@ -12,3 +12,4 @@ export function getBasename(filename) {
12
12
  export function fileIdentityKey(file) {
13
13
  return `${file.name}-${file.size}-${file.lastModified}`;
14
14
  }
15
+ //# sourceMappingURL=file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.js","sourceRoot":"","sources":["../src/file.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,YAAY,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE/C,IAAI,YAAY,IAAI,CAAC,IAAI,YAAY,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,QAAQ,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,YAAY,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE/C,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAU;IACxC,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;AAC1D,CAAC"}
package/dist/humanize.js CHANGED
@@ -65,3 +65,4 @@ export function humanDuration(args) {
65
65
  format: largest ? getDurationFormat(duration, largest) : undefined,
66
66
  });
67
67
  }
68
+ //# sourceMappingURL=humanize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"humanize.js","sourceRoot":"","sources":["../src/humanize.ts"],"names":[],"mappings":"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"}
@@ -13,3 +13,4 @@ export function splitIdentifierWords(raw) {
13
13
  .reduce((text, [pattern, replacement]) => text.replace(new RegExp(pattern, "g"), replacement), raw)
14
14
  .trim();
15
15
  }
16
+ //# sourceMappingURL=identifier-words.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identifier-words.js","sourceRoot":"","sources":["../src/identifier-words.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,MAAM,CAAC,MAAM,mBAAmB,GAAmE;IACjG,CAAC,GAAG,EAAE,GAAG,CAAC;IACV,CAAC,gBAAgB,EAAE,OAAO,CAAC;IAC3B,CAAC,qBAAqB,EAAE,OAAO,CAAC;IAChC,CAAC,gBAAgB,EAAE,OAAO,CAAC;IAC3B,CAAC,qBAAqB,EAAE,OAAO,CAAC;IAChC,CAAC,WAAW,EAAE,MAAM,CAAC;IACrB,CAAC,KAAK,EAAE,GAAG,CAAC;CACb,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,OAAO,mBAAmB;SACvB,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC;SAClG,IAAI,EAAE,CAAC;AACZ,CAAC"}
package/dist/number.js CHANGED
@@ -7,3 +7,4 @@ export function parseInteger(input) {
7
7
  }
8
8
  return;
9
9
  }
10
+ //# sourceMappingURL=number.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number.js","sourceRoot":"","sources":["../src/number.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,KAAqB;IAChD,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACnB,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAED,OAAO;AACT,CAAC"}
@@ -8,3 +8,4 @@ export const revokeObjectURL = (url) => {
8
8
  URL.revokeObjectURL(url);
9
9
  }
10
10
  };
11
+ //# sourceMappingURL=object-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-url.js","sourceRoot":"","sources":["../src/object-url.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAA6B,EAAU,EAAE;IACvE,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,OAAO,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAW,EAAQ,EAAE;IACnD,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC,CAAC"}
package/dist/present.js CHANGED
@@ -21,3 +21,4 @@ export function isPresent(value) {
21
21
  }
22
22
  return true;
23
23
  }
24
+ //# sourceMappingURL=present.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"present.js","sourceRoot":"","sources":["../src/present.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAMlD,MAAM,UAAU,SAAS,CAAI,KAA2B;IACtD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/C,IAAI,KAAK,YAAY,GAAG,IAAI,KAAK,YAAY,GAAG;YAAE,OAAO,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;QACxE,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY,WAAW;YAAE,OAAO,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;QAE3F,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAC/C,OAAO,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI,CAAC;IAC9D,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
package/dist/set.js CHANGED
@@ -29,3 +29,4 @@ export function addAll(set, items) {
29
29
  }
30
30
  throw new Error("Unsupported type");
31
31
  }
32
+ //# sourceMappingURL=set.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set.js","sourceRoot":"","sources":["../src/set.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,yEAAyE;AACzE,MAAM,UAAU,UAAU,CAAI,KAAa;IACzC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,UAAU,CAAC,8DAA8D,KAAK,GAAG,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,GAAG,EAAK,CAAC;IACzB,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE9C,GAAG,CAAC,GAAG,GAAG,CAAC,KAAK,EAAE,EAAE;QAClB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,KAAK;YAAE,YAAY,CAAC,GAAG,CAAC,CAAC;QAC5D,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,YAAY,CAAI,GAAW;IAClC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,CAAC,MAAM,CAAC,IAAI;QAAE,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC;AAID,MAAM,UAAU,MAAM,CAAI,GAAW,EAAE,KAAc;IACnD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IAED,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;AACtC,CAAC"}
package/dist/sleep.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export function sleep(ms) {
2
2
  return new Promise((resolve) => setTimeout(resolve, ms));
3
3
  }
4
+ //# sourceMappingURL=sleep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep.js","sourceRoot":"","sources":["../src/sleep.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
package/dist/string.js CHANGED
@@ -11,3 +11,4 @@ export function getInitials(args) {
11
11
  .slice(0, maxCount)
12
12
  .join("");
13
13
  }
14
+ //# sourceMappingURL=string.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string.js","sourceRoot":"","sources":["../src/string.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAE7B,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChD,CAAC;AAID,MAAM,UAAU,WAAW,CAAC,IAAqB;IAC/C,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,GAAG,EAAE,QAAQ,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC;IAErD,OAAO,IAAI;SACR,KAAK,CAAC,SAAS,CAAC;SAChB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;SACzD,MAAM,CAAC,OAAO,CAAC;SACf,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC;SAClB,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
package/dist/types.js CHANGED
@@ -1 +1,2 @@
1
1
  export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/dist/url.js CHANGED
@@ -38,3 +38,4 @@ export function mergeURLParams(url, params) {
38
38
  mergeAll(url.searchParams, params);
39
39
  return url;
40
40
  }
41
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,KAAK,CAAC,GAAY;IAChC,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAO,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,KAAK,EAAE,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAY;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QAE1B,OAAO,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAID,MAAM,UAAU,QAAQ,CAAC,EAAmB,EAAE,MAAmB;IAC/D,IAAI,MAAM,YAAY,eAAe,EAAE,CAAC;QACtC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YAClC,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;SAAM,IAAI,MAAM,YAAY,GAAG,EAAE,CAAC;QACjC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YAClC,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAQ,EAAE,MAAmB;IAC1D,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,GAAG,CAAC;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manta-eu/lib",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Pure TypeScript helpers shared across the Manta packages",
5
5
  "homepage": "https://developers.manta.eu",
6
6
  "keywords": [
@@ -19,7 +19,12 @@
19
19
  }
20
20
  },
21
21
  "files": [
22
- "dist"
22
+ "dist",
23
+ "src",
24
+ "!src/**/*.test.*",
25
+ "!src/**/*.stories.*",
26
+ "!src/**/__fixtures__",
27
+ "!src/coverage"
23
28
  ],
24
29
  "dependencies": {
25
30
  "date-fns": "^4.1.0",
@@ -0,0 +1,20 @@
1
+ export type MetaAdsManagerCampaignLinkOptions = {
2
+ adAccountExternalId: string;
3
+ campaignExternalId: string[];
4
+ /** Meta business the ad account is shared with; omit when the link is not going through one. */
5
+ partnerBusinessId?: string;
6
+ };
7
+
8
+ export function generateMetaAdsManagerCampaignLink(args: MetaAdsManagerCampaignLinkOptions) {
9
+ const { adAccountExternalId, campaignExternalId, partnerBusinessId } = args;
10
+ const recordSeparator = String.fromCharCode(0x1e);
11
+ const campaignIds = campaignExternalId.map((id) => `"${id}"`).join(",");
12
+ const filterSet = `SEARCH_BY_CAMPAIGN_GROUP_IDS-STRING_SET${recordSeparator}ANY${recordSeparator}[${campaignIds}]`;
13
+ const url = new URL("https://adsmanager.facebook.com/adsmanager/manage/campaigns");
14
+ url.searchParams.set("act", adAccountExternalId);
15
+ if (partnerBusinessId) {
16
+ url.searchParams.set("business_id", partnerBusinessId);
17
+ }
18
+ url.searchParams.set("filter_set", filterSet);
19
+ return url.toString();
20
+ }
package/src/array.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { update } from "ramda";
2
+
3
+ export function arrayWrap<T>(value: T | T[]): T[] {
4
+ return Array.isArray(value) ? value : [value];
5
+ }
6
+
7
+ export function replaceAtIndex<T>(arr: T[], index: number, item: T): T[] {
8
+ return update(index, item, arr);
9
+ }
@@ -0,0 +1,70 @@
1
+ export type ParsedAssetFilename<TRatio> = {
2
+ baseName: string;
3
+ ratio: TRatio | undefined;
4
+ };
5
+
6
+ export type ParseAssetFilenameWithSuffixMapProps<TRatio> = {
7
+ filename: string;
8
+ suffixMap: Record<string, TRatio>;
9
+ };
10
+
11
+ export function parseAssetFilenameWithSuffixMap<TRatio>(
12
+ props: ParseAssetFilenameWithSuffixMapProps<TRatio>,
13
+ ): ParsedAssetFilename<TRatio> {
14
+ const { filename, suffixMap } = props;
15
+ const nameWithoutExt = filename.replace(/\.[^.]+$/, "");
16
+ const lower = nameWithoutExt.toLowerCase();
17
+ const suffixEntries = Object.entries(suffixMap).sort((a, b) => b[0].length - a[0].length);
18
+
19
+ for (const [suffix, ratio] of suffixEntries) {
20
+ if (!lower.endsWith(suffix)) continue;
21
+ const rawBaseName = nameWithoutExt.slice(0, -suffix.length);
22
+ const baseName = rawBaseName.replace(/[_\-\s]+$/, "").trim();
23
+ return { baseName: baseName || nameWithoutExt, ratio };
24
+ }
25
+
26
+ return { baseName: nameWithoutExt.trim(), ratio: undefined };
27
+ }
28
+
29
+ export type UploadGroupingItem<TAsset, TRatio> = {
30
+ asset: TAsset;
31
+ ratio: TRatio | undefined;
32
+ baseName: string;
33
+ };
34
+
35
+ export type UploadedAssetGroup<TAsset, TRatio> = {
36
+ baseName: string;
37
+ assets: Array<{ asset: TAsset; ratio: TRatio }>;
38
+ };
39
+
40
+ export type GroupUploadedAssetsByBaseNameProps<TAsset, TRatio> = {
41
+ results: UploadGroupingItem<TAsset, TRatio>[];
42
+ };
43
+
44
+ export function groupUploadedAssetsByBaseName<TAsset, TRatio>(
45
+ props: GroupUploadedAssetsByBaseNameProps<TAsset, TRatio>,
46
+ ): {
47
+ groups: UploadedAssetGroup<TAsset, TRatio>[];
48
+ unmatched: TAsset[];
49
+ } {
50
+ const { results } = props;
51
+ const groupMap = new Map<string, UploadedAssetGroup<TAsset, TRatio>>();
52
+ const unmatched: TAsset[] = [];
53
+
54
+ for (const result of results) {
55
+ if (result.ratio === undefined || result.baseName.trim() === "") {
56
+ unmatched.push(result.asset);
57
+ continue;
58
+ }
59
+
60
+ const key = result.baseName.toLowerCase();
61
+ const group = groupMap.get(key) ?? { baseName: result.baseName, assets: [] };
62
+ group.assets.push({ asset: result.asset, ratio: result.ratio });
63
+ groupMap.set(key, group);
64
+ }
65
+
66
+ return {
67
+ groups: [...groupMap.values()],
68
+ unmatched,
69
+ };
70
+ }
package/src/backoff.ts ADDED
@@ -0,0 +1,14 @@
1
+ export type Backoff = {
2
+ initialMs: number;
3
+ maxMs: number;
4
+ factor?: number;
5
+ // A random share of the delay, added so that many clients do not retry at the same moment.
6
+ jitterRatio?: number;
7
+ };
8
+
9
+ export function backoffDelayMs(attempt: number, backoff: Backoff, random: () => number = Math.random): number {
10
+ const { initialMs, maxMs, factor = 2, jitterRatio = 0 } = backoff;
11
+ const exponential = initialMs * factor ** Math.max(0, attempt);
12
+ const jitter = random() * exponential * jitterRatio;
13
+ return Math.min(maxMs, exponential + jitter);
14
+ }
package/src/color.ts ADDED
@@ -0,0 +1,92 @@
1
+ import type { DateArg } from "date-fns";
2
+ import { differenceInHours } from "date-fns";
3
+
4
+ export type RGBColor = {
5
+ r: number;
6
+ g: number;
7
+ b: number;
8
+ };
9
+
10
+ export type HexColor = `#${string}`;
11
+
12
+ export const hexToRgb = (hex: HexColor): RGBColor => {
13
+ let sanitizedHex = hex.replace("#", "");
14
+
15
+ if (sanitizedHex.length === 3) {
16
+ sanitizedHex = sanitizedHex
17
+ .split("")
18
+ .map((h) => `${h}${h}`)
19
+ .join("");
20
+ }
21
+
22
+ const bigint = parseInt(sanitizedHex, 16);
23
+
24
+ if (isNaN(bigint)) throw new Error(`Invalid hex value: ${hex}`);
25
+
26
+ return {
27
+ r: (bigint >> 16) & 255,
28
+ g: (bigint >> 8) & 255,
29
+ b: bigint & 255,
30
+ };
31
+ };
32
+
33
+ export function rgbToHex({ r, g, b }: RGBColor): HexColor {
34
+ const componentToHex = (c: number) => {
35
+ const hex = c.toString(16);
36
+ return hex.length === 1 ? `0${hex}` : hex;
37
+ };
38
+
39
+ return `#${componentToHex(r)}${componentToHex(g)}${componentToHex(b)}`;
40
+ }
41
+
42
+ export function capBrightness(hexColor: HexColor, maxBrightness: number = 150): string {
43
+ let { r, g, b } = hexToRgb(hexColor);
44
+
45
+ r = Math.min(r, maxBrightness);
46
+ g = Math.min(g, maxBrightness);
47
+ b = Math.min(b, maxBrightness);
48
+
49
+ return rgbToHex({ r, g, b });
50
+ }
51
+
52
+ export const generateHexColorBasedOnName = (name: string) => {
53
+ const hash = name.split("").reduce((acc, char) => acc + char.charCodeAt(0), 0);
54
+
55
+ const color = `hsl(${hash % 360}, 50%, 50%)`;
56
+ const contrast = hash % 360 > 180 ? "black" : "white";
57
+
58
+ return { color, contrast };
59
+ };
60
+
61
+ export const getAverageColor = (ctx: CanvasRenderingContext2D, width: number, height: number): RGBColor => {
62
+ const imageData = ctx.getImageData(0, 0, width, height);
63
+ const data = imageData.data;
64
+ const length = data.length;
65
+
66
+ let r = 0,
67
+ g = 0,
68
+ b = 0,
69
+ count = 0;
70
+
71
+ for (let i = 0; i < length; i += 4) {
72
+ r += data[i]!;
73
+ g += data[i + 1]!;
74
+ b += data[i + 2]!;
75
+ count++;
76
+ }
77
+
78
+ return {
79
+ r: Math.floor(r / count),
80
+ g: Math.floor(g / count),
81
+ b: Math.floor(b / count),
82
+ };
83
+ };
84
+
85
+ export function getAgeColor(date: DateArg<Date>): string {
86
+ const diffInHours = differenceInHours(Date.now(), date);
87
+ const clampedHours = Math.min(Math.max(diffInHours, 0), 36);
88
+
89
+ const hue = Math.round(120 - clampedHours * 3.3333);
90
+
91
+ return `hsl(${hue}, 80%, 40%)`;
92
+ }
@@ -0,0 +1,95 @@
1
+ import { isPresent } from "./present";
2
+
3
+ export type ConnectionString = {
4
+ scheme: string;
5
+ host?: string;
6
+ port?: string;
7
+ username?: string;
8
+ password?: string;
9
+ path: string[];
10
+ params: Record<string, string>;
11
+ };
12
+
13
+ export type ParseOptions = {
14
+ // A URL can hold a raw ";" in its user name or password, so only a JDBC format that uses ";KEY=VALUE" sets this.
15
+ semicolonProperties?: boolean;
16
+ };
17
+
18
+ export function parseConnectionString(input: string, options: ParseOptions = {}): ConnectionString | undefined {
19
+ const { semicolonProperties = false } = options;
20
+ const schemeAndRest = splitScheme(stripJdbcPrefix(input.trim()));
21
+ if (!schemeAndRest) return undefined;
22
+
23
+ const { scheme, rest } = schemeAndRest;
24
+ const [head, properties] = semicolonProperties ? splitHead(rest) : [rest, ""];
25
+ if (head.includes("\\")) return undefined;
26
+
27
+ try {
28
+ const { path, query, ...authority } = headParts(scheme, head, semicolonProperties);
29
+ return {
30
+ scheme,
31
+ ...withoutBlankValues(authority),
32
+ path,
33
+ params: Object.fromEntries([...query, ...propertyEntries(properties)]),
34
+ };
35
+ } catch {
36
+ return undefined;
37
+ }
38
+ }
39
+
40
+ export function unescapeBracedValue(value: string): string {
41
+ const braced = /^\{(.*)\}$/s.exec(value);
42
+ return braced?.[1] === undefined ? value : braced[1].replaceAll("}}", "}");
43
+ }
44
+
45
+ function stripJdbcPrefix(input: string): string {
46
+ return input.replace(/^jdbc:/i, "");
47
+ }
48
+
49
+ const schemePattern = /^([a-z][a-z0-9+.-]*):\/\//i;
50
+
51
+ function splitScheme(text: string): { scheme: string; rest: string } | undefined {
52
+ const match = schemePattern.exec(text);
53
+ if (!match?.[1]) return undefined;
54
+ return { scheme: match[1].toLowerCase(), rest: text.slice(match[0].length) };
55
+ }
56
+
57
+ function splitHead(text: string): [string, string] {
58
+ const [head = "", ...properties] = text.split(";");
59
+ return [head, properties.join(";")];
60
+ }
61
+
62
+ // The BigQuery JDBC head is an endpoint URL, so a head with its own scheme carries no host.
63
+ function headParts(scheme: string, head: string, semicolonProperties: boolean) {
64
+ if (!isPresent(head) || (semicolonProperties && head.includes("://"))) return { path: [], query: [] };
65
+ return urlParts(scheme, head);
66
+ }
67
+
68
+ function urlParts(scheme: string, head: string) {
69
+ const url = new URL(`${scheme}://${head}`);
70
+
71
+ return {
72
+ host: url.hostname.replace(/^\[(.*)\]$/, "$1"),
73
+ port: url.port,
74
+ username: decodeURIComponent(url.username),
75
+ password: decodeURIComponent(url.password),
76
+ path: url.pathname.split("/").filter(Boolean).map(decodeURIComponent),
77
+ query: [...url.searchParams],
78
+ };
79
+ }
80
+
81
+ function withoutBlankValues(entries: Record<string, string>): Record<string, string> {
82
+ return Object.fromEntries(Object.entries(entries).filter(([, value]) => isPresent(value)));
83
+ }
84
+
85
+ const propertyName = "([^;=]+)";
86
+ // The SQL Server JDBC driver escapes a value in braces, and "}}" in the braces stands for one "}".
87
+ const bracedValue = String.raw`\{(?:[^}]|\}\})*\}`;
88
+ const plainValue = "[^;]*";
89
+ const propertyPattern = new RegExp(String.raw`${propertyName}=\s*(${bracedValue}|${plainValue})`, "g");
90
+
91
+ function propertyEntries(text: string): [string, string][] {
92
+ return [...text.matchAll(propertyPattern)]
93
+ .map(([, name = "", value = ""]): [string, string] => [name.trim(), value.trim()])
94
+ .filter(([name]) => isPresent(name));
95
+ }
@@ -0,0 +1,18 @@
1
+ const regionDisplayNames = new Intl.DisplayNames(["en"], { type: "region" });
2
+ const languageDisplayNames = new Intl.DisplayNames(["en"], { type: "language" });
3
+
4
+ export function getCountryName(countryCode: string) {
5
+ try {
6
+ return regionDisplayNames.of(countryCode) ?? countryCode;
7
+ } catch {
8
+ return countryCode;
9
+ }
10
+ }
11
+
12
+ export function getLanguageName(languageCode: string) {
13
+ try {
14
+ return languageDisplayNames.of(languageCode.toLowerCase()) ?? languageCode;
15
+ } catch {
16
+ return languageCode;
17
+ }
18
+ }
package/src/date.ts ADDED
@@ -0,0 +1,51 @@
1
+ import type { DateArg, FormatOptions } from "date-fns";
2
+ import { format, formatISO, set } from "date-fns";
3
+ import { take } from "ramda";
4
+ import { parseInteger } from "./number";
5
+
6
+ export function setTime<DateType extends Date, ResultDate extends Date = DateType>(
7
+ date: DateArg<DateType>,
8
+ time: string,
9
+ ): ResultDate;
10
+
11
+ export function setTime<DateType extends Date, ResultDate extends Date = DateType>(
12
+ date: DateArg<DateType>,
13
+ hours: number,
14
+ minutes: number,
15
+ ): ResultDate;
16
+
17
+ export function setTime<DateType extends Date, ResultDate extends Date = DateType>(
18
+ date: DateArg<DateType>,
19
+ timeOrHour: string | number,
20
+ optMinutes?: number,
21
+ ): ResultDate {
22
+ let hours: number | undefined;
23
+ let minutes: number | undefined;
24
+
25
+ if (typeof timeOrHour === "string") {
26
+ [hours, minutes] = take(2, timeOrHour.split(":", 3)).map(parseInteger);
27
+ } else {
28
+ hours = timeOrHour;
29
+ minutes = optMinutes;
30
+ }
31
+
32
+ return set(date, { hours, minutes, seconds: 0, milliseconds: 0 });
33
+ }
34
+
35
+ export function formatDate(date: DateArg<Date> & {}): string {
36
+ return format(date, "yyyy-MM-dd");
37
+ }
38
+
39
+ export function formatISODate(date: DateArg<Date>): string {
40
+ return formatISO(date, { representation: "date" });
41
+ }
42
+
43
+ export type FormatTimeOptions = Intl.DateTimeFormatOptions;
44
+
45
+ export function formatTime(date: Date, options: FormatTimeOptions = {}): string {
46
+ return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", ...options });
47
+ }
48
+
49
+ export function formatDateTime(date: DateArg<Date>, formatStr = "yyyy-MM-dd HH:mm", options?: FormatOptions): string {
50
+ return format(date, formatStr, options);
51
+ }
package/src/enum.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { identity } from "ramda";
2
+
3
+ export type Option<T extends string> = {
4
+ id: T;
5
+ label: string;
6
+ };
7
+
8
+ export function enumToOptions<T extends string>(
9
+ enums: T[],
10
+ labelFunction: (value: T) => string = identity,
11
+ ): Option<T>[] {
12
+ return enums
13
+ .map((value) => ({
14
+ id: value,
15
+ label: labelFunction(value),
16
+ }))
17
+ .sort((a, b) => a.label.localeCompare(b.label));
18
+ }
@@ -0,0 +1,27 @@
1
+ import { isPresent } from "./present";
2
+
3
+ export const externalAppClientIdPrefix = "ext-";
4
+
5
+ const loopbackHosts = new Set(["localhost", "127.0.0.1", "[::1]"]);
6
+ const maxRedirectUrlLength = 2048;
7
+
8
+ // Keycloak compares a redirect URL with what the app sends as an exact string, so it is stored as typed.
9
+ export function redirectUrlProblem(raw: string): string | undefined {
10
+ if (raw.length > maxRedirectUrlLength) return `Keep it under ${maxRedirectUrlLength} characters`;
11
+ if (raw.includes("*")) return "Wildcards are not allowed";
12
+ if (/[\s,]/.test(raw)) return "Leave out commas and spaces, one URL per field";
13
+
14
+ let url: URL;
15
+ try {
16
+ url = new URL(raw);
17
+ } catch {
18
+ return "Enter a full URL, like https://app.example.com/callback";
19
+ }
20
+
21
+ if (url.protocol !== "https:" && !(url.protocol === "http:" && loopbackHosts.has(url.hostname))) {
22
+ return "Use https, or http for localhost";
23
+ }
24
+ if (isPresent(url.username) || isPresent(url.password)) return "Leave out the username and password";
25
+ if (isPresent(url.hash)) return "Leave out the #fragment";
26
+ return undefined;
27
+ }
package/src/file.ts ADDED
@@ -0,0 +1,19 @@
1
+ export function getExtension(filename: string) {
2
+ const lastDotIndex = filename.lastIndexOf(".");
3
+
4
+ if (lastDotIndex <= 0 || lastDotIndex === filename.length - 1) {
5
+ return undefined;
6
+ }
7
+
8
+ return filename.slice(lastDotIndex + 1).toLowerCase();
9
+ }
10
+
11
+ export function getBasename(filename: string) {
12
+ const lastDotIndex = filename.lastIndexOf(".");
13
+
14
+ return lastDotIndex === -1 ? filename : filename.slice(0, lastDotIndex);
15
+ }
16
+
17
+ export function fileIdentityKey(file: File) {
18
+ return `${file.name}-${file.size}-${file.lastModified}`;
19
+ }
@@ -0,0 +1,94 @@
1
+ import type { DateArg, Duration, DurationUnit } from "date-fns";
2
+ import { formatDuration, intervalToDuration } from "date-fns";
3
+ import { filesize } from "filesize";
4
+ import pluralize from "pluralize";
5
+ import { isPresent } from "./present";
6
+
7
+ export function humanBytes(input: number): string {
8
+ return filesize(input, {
9
+ base: 2,
10
+ separator: ".",
11
+ standard: "jedec",
12
+ }) as string;
13
+ }
14
+
15
+ export function humanCount(count: number, word: string): string {
16
+ return pluralize(word, count, true);
17
+ }
18
+
19
+ export function humanNumber(num: bigint | number): string {
20
+ const n = Number(num);
21
+ if (n >= 1000000) {
22
+ return `${(n / 1000000).toFixed(1)}M`;
23
+ }
24
+ if (n >= 1000) {
25
+ return `${(n / 1000).toFixed(1)}K`;
26
+ }
27
+ return n.toString();
28
+ }
29
+
30
+ export function humanizeEnum(value: string | undefined): string | undefined {
31
+ if (!isPresent(value)) return undefined;
32
+
33
+ return value
34
+ .toLowerCase()
35
+ .split(/[_-]/)
36
+ .filter(isPresent)
37
+ .map((word) => `${word.charAt(0).toUpperCase()}${word.slice(1)}`)
38
+ .join(" ");
39
+ }
40
+
41
+ export function humanDimensions({ width, height }: { width: number; height: number }): string {
42
+ return `${width}x${height}`;
43
+ }
44
+
45
+ export function humanPlural(word: string, count: number): string {
46
+ return pluralize(word, count, false);
47
+ }
48
+
49
+ export type HumanListOptions = Intl.ListFormatOptions & {
50
+ truncateAt?: number;
51
+ };
52
+
53
+ export function humanList(list: string[], options?: HumanListOptions): string {
54
+ const { truncateAt, ...formatOptions } = options || {};
55
+ const listFormat = new Intl.ListFormat("en", formatOptions);
56
+
57
+ if (!truncateAt || list.length <= truncateAt) {
58
+ return listFormat.format(list);
59
+ }
60
+
61
+ const remaining = list.length - truncateAt;
62
+ const truncated = [...list.slice(0, truncateAt), `+${remaining} more`];
63
+
64
+ return listFormat.format(truncated);
65
+ }
66
+
67
+ export type HumanDurationArgs = {
68
+ start: DateArg<Date>;
69
+ end: DateArg<Date>;
70
+ largest?: number;
71
+ };
72
+
73
+ const periods = ["years", "months", "weeks", "days", "hours", "minutes", "seconds"] as const satisfies DurationUnit[];
74
+
75
+ function getDurationFormat(duration: Duration, largest: number): DurationUnit[] {
76
+ const formats = periods.reduce((acc, period) => {
77
+ return acc.length < largest && duration[period] ? [...acc, period] : acc;
78
+ }, [] as DurationUnit[]);
79
+
80
+ return formats.length === 0 ? ["seconds"] : formats;
81
+ }
82
+
83
+ export function humanDuration(args: HumanDurationArgs): string {
84
+ const { start, end, largest } = args;
85
+
86
+ const duration = intervalToDuration({
87
+ start,
88
+ end,
89
+ });
90
+
91
+ return formatDuration(duration, {
92
+ format: largest ? getDurationFormat(duration, largest) : undefined,
93
+ });
94
+ }
@@ -0,0 +1,16 @@
1
+ // Splits a programmer identifier into words: `actionPlan_v2` becomes `action Plan v2`.
2
+ export const identifierWordRules: ReadonlyArray<readonly [pattern: string, replacement: string]> = [
3
+ ["_", " "],
4
+ ["([a-z])([A-Z])", "$1 $2"],
5
+ ["([A-Z])([A-Z][a-z])", "$1 $2"],
6
+ ["([a-z])([0-9])", "$1 $2"],
7
+ ["([0-9])([A-Z][a-z])", "$1 $2"],
8
+ ["([0-9]+)x", " $1x"],
9
+ [" *", " "],
10
+ ];
11
+
12
+ export function splitIdentifierWords(raw: string): string {
13
+ return identifierWordRules
14
+ .reduce((text, [pattern, replacement]) => text.replace(new RegExp(pattern, "g"), replacement), raw)
15
+ .trim();
16
+ }
package/src/number.ts ADDED
@@ -0,0 +1,10 @@
1
+ export function parseInteger(input?: string | null): number | undefined {
2
+ if (input && input.trim().length > 0) {
3
+ const number = parseInt(input, 10);
4
+ if (!isNaN(number)) {
5
+ return number;
6
+ }
7
+ }
8
+
9
+ return;
10
+ }
@@ -0,0 +1,10 @@
1
+ export const createObjectURL = (file: File | Blob | undefined): string => {
2
+ if (!file) return "";
3
+ return URL.createObjectURL(file);
4
+ };
5
+
6
+ export const revokeObjectURL = (url: string): void => {
7
+ if (url && url.startsWith("blob:")) {
8
+ URL.revokeObjectURL(url);
9
+ }
10
+ };
package/src/present.ts ADDED
@@ -0,0 +1,30 @@
1
+ // After https://apidock.com/rails/Object/blank%3F
2
+
3
+ export function isPresent(value: string | null | undefined): value is string;
4
+ export function isPresent<T>(value: T[] | null | undefined): value is [T, ...T[]];
5
+ export function isPresent(value: Record<string, unknown> | null | undefined): value is Record<string, unknown>;
6
+ export function isPresent<T>(value: T | null | undefined): value is T;
7
+ export function isPresent<T>(value: T | null | undefined): value is NonNullable<T> {
8
+ if (value === null || value === undefined || value === false) {
9
+ return false;
10
+ }
11
+
12
+ if (typeof value === "string") {
13
+ return value.trim().length > 0;
14
+ }
15
+
16
+ if (Array.isArray(value)) {
17
+ return value.length > 0;
18
+ }
19
+
20
+ if (typeof value === "object") {
21
+ if (Object.keys(value).length > 0) return true;
22
+ if (value instanceof Map || value instanceof Set) return value.size > 0;
23
+ if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) return value.byteLength > 0;
24
+
25
+ const prototype = Object.getPrototypeOf(value);
26
+ return prototype !== Object.prototype && prototype !== null;
27
+ }
28
+
29
+ return true;
30
+ }
package/src/set.ts ADDED
@@ -0,0 +1,38 @@
1
+ // A Set that removes its oldest member to make room when it is full. Only its add method changes.
2
+ // A copy such as `new Set(bounded)` keeps the members but not the limit.
3
+ export function boundedSet<T>(limit: number): Set<T> {
4
+ if (!Number.isInteger(limit) || limit < 1) {
5
+ throw new RangeError(`A bounded set needs a whole limit of 1 or more, but it got ${limit}.`);
6
+ }
7
+
8
+ const set = new Set<T>();
9
+ const nativeAdd = Set.prototype.add.bind(set);
10
+
11
+ set.add = (value) => {
12
+ if (!set.has(value) && set.size >= limit) removeOldest(set);
13
+ return nativeAdd(value);
14
+ };
15
+
16
+ return set;
17
+ }
18
+
19
+ function removeOldest<T>(set: Set<T>): void {
20
+ const oldest = set.values().next();
21
+ if (!oldest.done) set.delete(oldest.value);
22
+ }
23
+
24
+ export function addAll<T>(set: Set<T>, items: Array<T>): void;
25
+ export function addAll<T>(set: Set<T>, other: Set<T>): void;
26
+ export function addAll<T>(set: Set<T>, items: unknown): void {
27
+ if (Array.isArray(items)) {
28
+ items.forEach((item) => set.add(item));
29
+ return;
30
+ }
31
+
32
+ if (items instanceof Set) {
33
+ items.forEach((item) => set.add(item));
34
+ return;
35
+ }
36
+
37
+ throw new Error("Unsupported type");
38
+ }
package/src/sleep.ts ADDED
@@ -0,0 +1,3 @@
1
+ export function sleep(ms: number): Promise<void> {
2
+ return new Promise((resolve) => setTimeout(resolve, ms));
3
+ }
package/src/string.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { trim } from "ramda";
2
+
3
+ export function trimLines(input: string) {
4
+ return input.split("\n").map(trim).join("\n");
5
+ }
6
+
7
+ export type GetInitialsArgs = { name: string; separator?: " "; maxCount?: number };
8
+
9
+ export function getInitials(args: GetInitialsArgs) {
10
+ const { name, separator = " ", maxCount = 2 } = args;
11
+
12
+ return name
13
+ .split(separator)
14
+ .map((part) => part.match(/[a-zA-Z]/)?.[0]?.toUpperCase())
15
+ .filter(Boolean)
16
+ .slice(0, maxCount)
17
+ .join("");
18
+ }
package/src/types.ts ADDED
@@ -0,0 +1 @@
1
+ export type Awaitable<T> = T | Promise<T>;
package/src/url.ts ADDED
@@ -0,0 +1,47 @@
1
+ export type URLLike = URL | string;
2
+
3
+ export function toURL(url: URLLike): URL {
4
+ return typeof url === "string" ? new URL(url) : url;
5
+ }
6
+
7
+ export function ensureProtocol(input: string): string {
8
+ return /^https?:\/\//i.test(input) ? input : `https://${input}`;
9
+ }
10
+
11
+ export function getHostname(url: URLLike): string {
12
+ return toURL(url).hostname;
13
+ }
14
+
15
+ export function isHttpURL(url: URLLike): boolean {
16
+ try {
17
+ const parsed = toURL(url);
18
+
19
+ return parsed.protocol === "http:" || parsed.protocol === "https:";
20
+ } catch {
21
+ return false;
22
+ }
23
+ }
24
+
25
+ export type ParamsInput = URLSearchParams | Map<string, string> | Record<string, string>;
26
+
27
+ export function mergeAll(to: URLSearchParams, params: ParamsInput): URLSearchParams {
28
+ if (params instanceof URLSearchParams) {
29
+ for (const [key, value] of params) {
30
+ to.set(key, value);
31
+ }
32
+ } else if (params instanceof Map) {
33
+ for (const [key, value] of params) {
34
+ to.set(key, value);
35
+ }
36
+ } else {
37
+ for (const [key, value] of Object.entries(params)) {
38
+ to.set(key, value);
39
+ }
40
+ }
41
+ return to;
42
+ }
43
+
44
+ export function mergeURLParams(url: URL, params: ParamsInput): URL {
45
+ mergeAll(url.searchParams, params);
46
+ return url;
47
+ }