@dcl/hooks 2.0.0 → 2.0.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.
@@ -1,11 +1,12 @@
1
1
  import { AdvancedNavigatorUAData } from "./useAdvancedUserAgentData.type";
2
2
  /** @internal Reset module-level cache — only for testing. */
3
- export declare function resetUserAgentCache(): void;
3
+ declare function resetUserAgentCache(): void;
4
4
  /**
5
5
  * extract or infer the [UserAgentData](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgentData)
6
6
  * that is an object which can be used to access the User-Agent Client Hints API.
7
7
  */
8
- export declare function useAdvancedUserAgentData(): [
8
+ declare function useAdvancedUserAgentData(): [
9
9
  boolean,
10
10
  AdvancedNavigatorUAData | undefined
11
11
  ];
12
+ export { resetUserAgentCache, useAdvancedUserAgentData };
@@ -3,6 +3,10 @@ import { UAParser } from "ua-parser-js";
3
3
  import { isAppleSilicon } from "ua-parser-js/device-detection";
4
4
  import { useAsyncEffect } from "../useAsyncEffect";
5
5
  const DEFAULT_VALUE = "Unknown";
6
+ // Upper bound for the Client Hints round trip. `getHighEntropyValues` can
7
+ // reject (permissions policy, blocked by the browser) or never settle, and the
8
+ // hook must still leave `isLoading` in a bounded time.
9
+ const CLIENT_HINTS_TIMEOUT_MS = 1500;
6
10
  // Module-level cache: the user agent never changes during a session, so once
7
11
  // resolved the result is reused across component remounts (React StrictMode,
8
12
  // Suspense boundaries, lazy chunks, etc.). Without this cache every remount
@@ -10,8 +14,48 @@ const DEFAULT_VALUE = "Unknown";
10
14
  // and causing a visible flash in any UI that depends on the detected OS.
11
15
  let _cachedData;
12
16
  let _cacheResolved = false;
17
+ /**
18
+ * Resolves with the value of `promise`, or `undefined` if it rejects or does
19
+ * not settle within `ms`. The timer is always cleared.
20
+ */
21
+ async function settleWithin(promise, ms) {
22
+ let timer;
23
+ const timeout = new Promise((resolve) => {
24
+ timer = setTimeout(() => resolve(undefined), ms);
25
+ });
26
+ try {
27
+ return await Promise.race([promise, timeout]);
28
+ }
29
+ catch {
30
+ return undefined;
31
+ }
32
+ finally {
33
+ clearTimeout(timer);
34
+ }
35
+ }
36
+ async function readWithClientHints(ua, uaResult) {
37
+ const [uaResultWithClientHints, os, cpu] = await Promise.all([
38
+ uaResult.withClientHints(),
39
+ ua.getOS().withClientHints(),
40
+ ua.getCPU().withClientHints(),
41
+ ]);
42
+ return {
43
+ os,
44
+ architecture: cpu.architecture,
45
+ uaResult: uaResultWithClientHints,
46
+ hintsBrowserName: uaResultWithClientHints.browser.name,
47
+ };
48
+ }
49
+ // A fresh result: `uaResult` may still be updated by Client Hints that settle later.
50
+ function readFromUserAgent(ua) {
51
+ return {
52
+ os: ua.getOS(),
53
+ architecture: ua.getCPU().architecture,
54
+ uaResult: ua.getResult(),
55
+ };
56
+ }
13
57
  /** @internal Reset module-level cache — only for testing. */
14
- export function resetUserAgentCache() {
58
+ function resetUserAgentCache() {
15
59
  _cachedData = undefined;
16
60
  _cacheResolved = false;
17
61
  }
@@ -19,7 +63,7 @@ export function resetUserAgentCache() {
19
63
  * extract or infer the [UserAgentData](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgentData)
20
64
  * that is an object which can be used to access the User-Agent Client Hints API.
21
65
  */
22
- export function useAdvancedUserAgentData() {
66
+ function useAdvancedUserAgentData() {
23
67
  const [isLoading, setLoading] = useState(!_cacheResolved);
24
68
  const [data, setData] = useState(_cachedData);
25
69
  useAsyncEffect(async () => {
@@ -30,33 +74,41 @@ export function useAdvancedUserAgentData() {
30
74
  }
31
75
  setLoading(true);
32
76
  const ua = new UAParser(navigator.userAgent);
33
- const uaData = ua.getResult();
34
- const browser = {
35
- name: uaData.browser.name ?? DEFAULT_VALUE,
36
- version: uaData.browser.version ?? DEFAULT_VALUE,
37
- };
77
+ const uaResult = ua.getResult();
78
+ // Browser and engine come from the user-agent string. They are copied before
79
+ // the Client Hints call because `uaResult.withClientHints()` updates `uaResult`
80
+ // in place (and keeps doing so if the hints settle after the timeout).
38
81
  const engine = {
39
- name: uaData.engine.name ?? DEFAULT_VALUE,
40
- version: uaData.engine.version ?? DEFAULT_VALUE,
82
+ name: uaResult.engine.name ?? DEFAULT_VALUE,
83
+ version: uaResult.engine.version ?? DEFAULT_VALUE,
41
84
  };
42
- const [uaDataWithClientHints, osData, cpuData] = await Promise.all([
43
- uaData.withClientHints(),
44
- ua.getOS().withClientHints(),
45
- ua.getCPU().withClientHints(),
46
- ]);
85
+ const browser = {
86
+ name: uaResult.browser.name ?? DEFAULT_VALUE,
87
+ version: uaResult.browser.version ?? DEFAULT_VALUE,
88
+ };
89
+ // OS and CPU also use Client Hints, which are optional: if they reject or take
90
+ // too long, the user-agent string alone is used.
91
+ const parts = (await settleWithin(readWithClientHints(ua, uaResult), CLIENT_HINTS_TIMEOUT_MS)) ?? readFromUserAgent(ua);
92
+ // Brave sends a Chrome-form user agent. It is told apart by its Client Hints
93
+ // brand or, when the hints are missing, late or rejected, by `navigator.brave`
94
+ // (synchronous in ua-parser-js 2.x although typed as possibly async).
95
+ const featureChecked = ua.getBrowser().withFeatureCheck();
96
+ if (parts.hintsBrowserName === "Brave" || featureChecked.name === "Brave") {
97
+ browser.name = "Brave";
98
+ }
47
99
  const os = {
48
- name: osData.name ?? DEFAULT_VALUE,
49
- version: osData.version ?? DEFAULT_VALUE,
100
+ name: parts.os.name ?? DEFAULT_VALUE,
101
+ version: parts.os.version ?? DEFAULT_VALUE,
50
102
  };
51
103
  let architecture;
52
- if (!cpuData.architecture) {
104
+ if (!parts.architecture) {
53
105
  architecture =
54
- os.name === "macOS" && isAppleSilicon(uaDataWithClientHints)
106
+ os.name === "macOS" && isAppleSilicon(parts.uaResult)
55
107
  ? "arm64"
56
108
  : "Unknown";
57
109
  }
58
110
  else {
59
- architecture = cpuData.architecture;
111
+ architecture = parts.architecture;
60
112
  }
61
113
  const result = {
62
114
  browser,
@@ -75,4 +127,5 @@ export function useAdvancedUserAgentData() {
75
127
  }, []);
76
128
  return [isLoading, _cachedData ?? data];
77
129
  }
130
+ export { resetUserAgentCache, useAdvancedUserAgentData };
78
131
  //# sourceMappingURL=useAdvancedUserAgentData.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAdvancedUserAgentData.js","sourceRoot":"","sources":["../../../src/hooks/useAdvancedUserAgentData/useAdvancedUserAgentData.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useAdvancedUserAgentData.js","sourceRoot":"","sources":["../../../src/hooks/useAdvancedUserAgentData/useAdvancedUserAgentData.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcl/hooks",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "type": "module",
5
5
  "main": "esm/index.js",
6
6
  "module": "esm/index.js",
@@ -80,5 +80,5 @@
80
80
  "<rootDir>/test/setup.ts"
81
81
  ]
82
82
  },
83
- "commit": "05ecd74f92662acdf7bd81c3f60c1d676f456a2f"
83
+ "commit": "377b5c0587443779fe91cd52e27e9abfdcd9835a"
84
84
  }