@koloseum/utils 0.2.26 → 0.2.27

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/utils.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Database } from "@koloseum/types/database";
2
- import type { CustomError, Microservice, MicroserviceGroup, MicroserviceObject, UserWithCustomMetadata } from "@koloseum/types/general";
2
+ import type { BrowserInfo, CustomError, Microservice, MicroserviceGroup, MicroserviceObject, UserWithCustomMetadata } from "@koloseum/types/general";
3
3
  import type { BranchAddressObject, County, IdentityType, PronounsCheckboxes, PronounsItem, Sex, SocialMediaPlatform } from "@koloseum/types/public-auth";
4
4
  import type { Page } from "@sveltejs/kit";
5
5
  import type { SupabaseClient, FunctionInvokeOptions, PostgrestError } from "@supabase/supabase-js";
@@ -339,3 +339,56 @@ export declare const Cache: {
339
339
  */
340
340
  setData: <T>(valkey: any, cachePrefix: string, key: string, data: T, ttl?: number) => Promise<void>;
341
341
  };
342
+ export declare const Browser: {
343
+ /**
344
+ * Checks if a specific feature is supported by the browser.
345
+ * @param feature - The feature to check
346
+ * @param browserName - The name of the browser
347
+ * @param browserVersion - The version of the browser
348
+ * @returns `true` if the feature is supported, `false` otherwise
349
+ */
350
+ checkFeatureSupport: (feature: string, browserName: string, browserVersion: number) => boolean;
351
+ /**
352
+ * Gets detailed browser information for debugging.
353
+ */
354
+ getDetailedInfo: () => {
355
+ browser: string;
356
+ os: string;
357
+ platform: string;
358
+ engine: string;
359
+ userAgent: string;
360
+ };
361
+ /**
362
+ * Gets comprehensive browser information using Bowser.
363
+ */
364
+ getInfo: () => BrowserInfo;
365
+ /**
366
+ * Gets specific browser recommendations based on the detected browser.
367
+ */
368
+ getRecommendations: () => {
369
+ title: string;
370
+ message: string;
371
+ recommendations: string[];
372
+ critical: boolean;
373
+ };
374
+ /**
375
+ * Checks if the current browser is compatible with the application.
376
+ */
377
+ isBrowserCompatible: () => boolean;
378
+ /**
379
+ * Checks if the browser is Internet Explorer.
380
+ */
381
+ isInternetExplorer: () => boolean;
382
+ /**
383
+ * Checks if the browser is iOS Safari.
384
+ */
385
+ isIOSSafari: () => boolean;
386
+ /**
387
+ * Checks if the browser is a legacy version that needs updating.
388
+ */
389
+ isLegacyBrowser: () => boolean;
390
+ /**
391
+ * Checks if the browser is an old version of Safari.
392
+ */
393
+ isOldSafari: () => boolean;
394
+ };
package/dist/utils.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { v4 as uuidv4 } from "uuid";
2
2
  import { error as svelteError } from "@sveltejs/kit";
3
3
  import { FunctionsFetchError, FunctionsHttpError, FunctionsRelayError } from "@supabase/supabase-js";
4
+ import Bowser from "bowser";
4
5
  import validator from "validator";
5
6
  /* HELPERS */
6
7
  const parsePgInterval = (await import("postgres-interval")).default;
@@ -868,7 +869,7 @@ export const Utility = {
868
869
  isAuthorised = data;
869
870
  }
870
871
  // Validate SuprSend subscriber
871
- let personData;
872
+ let personData = {};
872
873
  if (user.app_metadata.person_data) {
873
874
  const { first_name: firstName, last_name: lastName, pseudonym } = user.app_metadata.person_data;
874
875
  personData = { firstName, lastName, phone: user.phone, pseudonym };
@@ -1729,3 +1730,286 @@ export const Cache = {
1729
1730
  }
1730
1731
  }
1731
1732
  };
1733
+ /* BROWSER COMPATIBILITY FUNCTIONS */
1734
+ export const Browser = {
1735
+ /**
1736
+ * Checks if a specific feature is supported by the browser.
1737
+ * @param feature - The feature to check
1738
+ * @param browserName - The name of the browser
1739
+ * @param browserVersion - The version of the browser
1740
+ * @returns `true` if the feature is supported, `false` otherwise
1741
+ */
1742
+ checkFeatureSupport: (feature, browserName, browserVersion) => {
1743
+ // Feature support matrix based on browser versions
1744
+ const featureSupport = {
1745
+ optionalChaining: {
1746
+ Chrome: 80,
1747
+ Firefox: 74,
1748
+ Safari: 13.4,
1749
+ Edge: 80,
1750
+ Opera: 80
1751
+ },
1752
+ nullishCoalescing: {
1753
+ Chrome: 80,
1754
+ Firefox: 72,
1755
+ Safari: 13.4,
1756
+ Edge: 80,
1757
+ Opera: 80
1758
+ },
1759
+ fetch: {
1760
+ Chrome: 42,
1761
+ Firefox: 39,
1762
+ Safari: 10.1,
1763
+ Edge: 14,
1764
+ Opera: 29
1765
+ },
1766
+ es6Modules: {
1767
+ Chrome: 61,
1768
+ Firefox: 60,
1769
+ Safari: 10.1,
1770
+ Edge: 16,
1771
+ Opera: 48
1772
+ },
1773
+ asyncAwait: {
1774
+ Chrome: 55,
1775
+ Firefox: 52,
1776
+ Safari: 10.1,
1777
+ Edge: 14,
1778
+ Opera: 42
1779
+ }
1780
+ };
1781
+ const featureMatrix = featureSupport[feature];
1782
+ if (!featureMatrix)
1783
+ return true; // Unknown feature, assume supported
1784
+ const minVersion = featureMatrix[browserName];
1785
+ if (!minVersion)
1786
+ return true; // Unknown browser, assume supported
1787
+ return browserVersion >= minVersion;
1788
+ },
1789
+ /**
1790
+ * Gets detailed browser information for debugging.
1791
+ */
1792
+ getDetailedInfo: () => {
1793
+ if (typeof window === "undefined") {
1794
+ return {
1795
+ browser: "Server-side rendering",
1796
+ os: "Unknown",
1797
+ platform: "Unknown",
1798
+ engine: "Unknown",
1799
+ userAgent: "Unknown"
1800
+ };
1801
+ }
1802
+ const browser = Bowser.getParser(window.navigator.userAgent);
1803
+ return {
1804
+ browser: `${browser.getBrowserName()} ${browser.getBrowserVersion()}`,
1805
+ os: `${browser.getOSName()} ${browser.getOSVersion()}`,
1806
+ platform: browser.getPlatformType(),
1807
+ engine: browser.getEngineName(),
1808
+ userAgent: window.navigator.userAgent
1809
+ };
1810
+ },
1811
+ /**
1812
+ * Gets comprehensive browser information using Bowser.
1813
+ */
1814
+ getInfo: () => {
1815
+ if (typeof window === "undefined") {
1816
+ return {
1817
+ name: "server",
1818
+ version: 0,
1819
+ isOldSafari: false,
1820
+ isIOS: false,
1821
+ supportsOptionalChaining: true,
1822
+ supportsNullishCoalescing: true,
1823
+ supportsFetch: true
1824
+ };
1825
+ }
1826
+ const browser = Bowser.getParser(window.navigator.userAgent);
1827
+ const browserName = browser.getBrowserName();
1828
+ const browserVersion = parseFloat(browser.getBrowserVersion() || "0");
1829
+ const osName = browser.getOSName();
1830
+ const isIOS = osName === "iOS";
1831
+ const isSafari = browserName === "Safari";
1832
+ const isOldSafari = isSafari && browserVersion < 13.4;
1833
+ return {
1834
+ name: browserName,
1835
+ version: browserVersion,
1836
+ isOldSafari,
1837
+ isIOS,
1838
+ supportsOptionalChaining: Browser.checkFeatureSupport("optionalChaining", browserName, browserVersion),
1839
+ supportsNullishCoalescing: Browser.checkFeatureSupport("nullishCoalescing", browserName, browserVersion),
1840
+ supportsFetch: Browser.checkFeatureSupport("fetch", browserName, browserVersion)
1841
+ };
1842
+ },
1843
+ /**
1844
+ * Gets specific browser recommendations based on the detected browser.
1845
+ */
1846
+ getRecommendations: () => {
1847
+ if (typeof window === "undefined")
1848
+ return {
1849
+ title: "Browser compatibility issue",
1850
+ message: "Browser detection is not available on theserver.",
1851
+ recommendations: [],
1852
+ critical: false
1853
+ };
1854
+ const browser = Bowser.getParser(window.navigator.userAgent);
1855
+ const browserName = browser.getBrowserName();
1856
+ const browserVersion = browser.getBrowserVersion();
1857
+ // Internet Explorer
1858
+ if (browserName === "Internet Explorer") {
1859
+ return {
1860
+ title: "Unsupported browser",
1861
+ message: "Internet Explorer is not supported. Please use a modern browser.",
1862
+ recommendations: [
1863
+ "Download and install Microsoft Edge",
1864
+ "Use an alternative such as Chrome or Firefox (or Safari on Mac)"
1865
+ ],
1866
+ critical: true
1867
+ };
1868
+ }
1869
+ // Apple Safari
1870
+ if (browserName === "Safari" && parseFloat(browserVersion || "0") < 13.4) {
1871
+ return {
1872
+ title: "Browser compatibility issue",
1873
+ message: `You're using Safari ${browserVersion || "Unknown"}, which doesn't support modern web features.`,
1874
+ recommendations: [
1875
+ "Update to Safari 13.4 or later",
1876
+ "Use Chrome or Firefox as an alternative",
1877
+ "Update your iOS device to the latest version"
1878
+ ],
1879
+ critical: true
1880
+ };
1881
+ }
1882
+ // Google Chrome
1883
+ if (browserName === "Chrome" && parseFloat(browserVersion || "0") < 80) {
1884
+ return {
1885
+ title: "Outdated browser",
1886
+ message: `You're using Chrome ${browserVersion || "Unknown"}, which may not support all features.`,
1887
+ recommendations: ["Update Chrome to version 80 or later", "Enable automatic updates in Chrome settings"],
1888
+ critical: false
1889
+ };
1890
+ }
1891
+ // Mozilla Firefox
1892
+ if (browserName === "Firefox" && parseFloat(browserVersion || "0") < 80) {
1893
+ return {
1894
+ title: "Outdated browser",
1895
+ message: `You're using Firefox ${browserVersion || "Unknown"}, which may not support all features.`,
1896
+ recommendations: ["Update Firefox to version 80 or later", "Enable automatic updates in Firefox settings"],
1897
+ critical: false
1898
+ };
1899
+ }
1900
+ // Microsoft Edge
1901
+ if (browserName === "Edge" && parseFloat(browserVersion || "0") < 80) {
1902
+ return {
1903
+ title: "Outdated browser",
1904
+ message: `You're using Edge ${browserVersion || "Unknown"}, which may not support all features.`,
1905
+ recommendations: ["Update Edge to version 80 or later", "Enable automatic updates in Edge settings"],
1906
+ critical: false
1907
+ };
1908
+ }
1909
+ // For unknown or very old browsers
1910
+ if (browserName === "Unknown" || parseFloat(browserVersion || "0") < 50) {
1911
+ return {
1912
+ title: "Unrecognised browser",
1913
+ message: "Your browser may not be fully supported. For the best experience, please use a modern browser.",
1914
+ recommendations: ["Use Chrome, Firefox or Edge (latest version)", "Use Safari 13.4+ (on Mac/iOS)"],
1915
+ critical: true
1916
+ };
1917
+ }
1918
+ // Default for modern browsers
1919
+ return {
1920
+ title: "Browser compatibility issue",
1921
+ message: "Your browser may not fully support this application.",
1922
+ recommendations: [
1923
+ "Update your browser to the latest version",
1924
+ "Clear your browser cache and cookies",
1925
+ "Disable browser extensions temporarily",
1926
+ "Try a different modern browser"
1927
+ ],
1928
+ critical: false
1929
+ };
1930
+ },
1931
+ /**
1932
+ * Checks if the current browser is compatible with the application.
1933
+ */
1934
+ isBrowserCompatible: () => {
1935
+ if (typeof window === "undefined")
1936
+ return true;
1937
+ const browser = Bowser.getParser(window.navigator.userAgent);
1938
+ const browserName = browser.getBrowserName();
1939
+ const browserVersion = parseFloat(browser.getBrowserVersion() || "0");
1940
+ // Define minimum supported versions
1941
+ const minVersions = {
1942
+ "Internet Explorer": 0, // Not supported at all
1943
+ Safari: 13.4,
1944
+ Chrome: 80,
1945
+ Firefox: 80,
1946
+ Edge: 80,
1947
+ Opera: 80
1948
+ };
1949
+ // Internet Explorer is never compatible
1950
+ if (browserName === "Internet Explorer") {
1951
+ return false;
1952
+ }
1953
+ // Check if browser version meets minimum requirements
1954
+ const minVersion = minVersions[browserName];
1955
+ if (minVersion && browserVersion < minVersion) {
1956
+ return false;
1957
+ }
1958
+ // Check for critical modern features
1959
+ return (Browser.checkFeatureSupport("optionalChaining", browserName, browserVersion) &&
1960
+ Browser.checkFeatureSupport("nullishCoalescing", browserName, browserVersion) &&
1961
+ Browser.checkFeatureSupport("fetch", browserName, browserVersion) &&
1962
+ Browser.checkFeatureSupport("es6Modules", browserName, browserVersion) &&
1963
+ Browser.checkFeatureSupport("asyncAwait", browserName, browserVersion));
1964
+ },
1965
+ /**
1966
+ * Checks if the browser is Internet Explorer.
1967
+ */
1968
+ isInternetExplorer: () => {
1969
+ if (typeof window === "undefined")
1970
+ return false;
1971
+ const browser = Bowser.getParser(window.navigator.userAgent);
1972
+ return browser.getBrowserName() === "Internet Explorer";
1973
+ },
1974
+ /**
1975
+ * Checks if the browser is iOS Safari.
1976
+ */
1977
+ isIOSSafari: () => {
1978
+ if (typeof window === "undefined")
1979
+ return false;
1980
+ const browser = Bowser.getParser(window.navigator.userAgent);
1981
+ return browser.getOSName() === "iOS" && browser.getBrowserName() === "Safari";
1982
+ },
1983
+ /**
1984
+ * Checks if the browser is a legacy version that needs updating.
1985
+ */
1986
+ isLegacyBrowser: () => {
1987
+ if (typeof window === "undefined")
1988
+ return false;
1989
+ const browser = Bowser.getParser(window.navigator.userAgent);
1990
+ const browserName = browser.getBrowserName();
1991
+ const browserVersion = parseFloat(browser.getBrowserVersion() || "0");
1992
+ // Legacy browser thresholds
1993
+ const legacyThresholds = {
1994
+ "Internet Explorer": 0, // All versions are legacy
1995
+ Safari: 13.4,
1996
+ Chrome: 80,
1997
+ Firefox: 80,
1998
+ Edge: 80,
1999
+ Opera: 80
2000
+ };
2001
+ const threshold = legacyThresholds[browserName];
2002
+ return threshold ? browserVersion < threshold : false;
2003
+ },
2004
+ /**
2005
+ * Checks if the browser is an old version of Safari.
2006
+ */
2007
+ isOldSafari: () => {
2008
+ if (typeof window === "undefined")
2009
+ return false;
2010
+ const browser = Bowser.getParser(window.navigator.userAgent);
2011
+ const browserName = browser.getBrowserName();
2012
+ const browserVersion = parseFloat(browser.getBrowserVersion() || "0");
2013
+ return browserName === "Safari" && browserVersion < 13.4;
2014
+ }
2015
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koloseum/utils",
3
- "version": "0.2.26",
3
+ "version": "0.2.27",
4
4
  "author": "Koloseum Technologies Limited",
5
5
  "type": "module",
6
6
  "description": "Utility logic for use across Koloseum web apps (TypeScript)",
@@ -31,6 +31,7 @@
31
31
  "dependencies": {
32
32
  "@supabase/supabase-js": "^2.57.4",
33
33
  "@sveltejs/kit": "^2.41.0",
34
+ "bowser": "^2.12.1",
34
35
  "kenya-administrative-divisions": "^0.0.18",
35
36
  "postgres-interval": "^4.0.2",
36
37
  "sanitize-html": "^2.17.0",
@@ -38,7 +39,7 @@
38
39
  "validator": "^13.15.15"
39
40
  },
40
41
  "devDependencies": {
41
- "@koloseum/types": "^0.2.8",
42
+ "@koloseum/types": "^0.2.10",
42
43
  "@playwright/test": "^1.55.0",
43
44
  "@suprsend/web-components": "^0.4.0",
44
45
  "@types/sanitize-html": "^2.16.0",