Socket
Socket
Sign inDemoInstall

react-user-agent-client-hints

Package Overview
Dependencies
3
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.2.1 to 0.2.2

dist/hooks/__tests__/useUserAgentData.test.d.ts

14

dist/hooks/useUserAgentData.d.ts

@@ -1,14 +0,4 @@

import { UADataValues, UALowEntropyJSON } from "../types";
export declare type Hint = "architecture" | "model" | "bitness" | "platformVersion" | "fullVersionList";
declare type HighEntropy = "high";
declare type LowEntropy = "low";
export declare function useUserAgentData(params: {
entropy: HighEntropy;
hints: Hint[];
}): UADataValues;
export declare function useUserAgentData(params: {
entropy: LowEntropy;
}): UALowEntropyJSON;
export declare function useUserAgentData(): UALowEntropyJSON;
declare type Hint = "brand" | "model" | "version" | "architecture" | "platform" | "mobile" | "platformVersion" | "uaFullVersion" | "bitness" | "wow64" | "fullVersionList";
export declare function useUserAgentData(hints: Hint[]): [UADataValues | null, Error | null];
export {};
//# sourceMappingURL=useUserAgentData.d.ts.map

@@ -14,92 +14,37 @@ "use strict";

const react_1 = require("react");
const HIGH_ENTROPY = "high";
const LOW_ENTROPY = "low";
/**
* Type-safe hook for accessing the current browser and operating system information.
* @param entropy Amount of information this hook reveals about the browser.
* @param hints Collection of strongly typed strings hinting to the returned user-agent data.
* @returns User agent data mapped from the hints argument or an error.
* @throws
*/
function useUserAgentData(params) {
function useUserAgentData(hints) {
const [userAgentData, setUserAgentData] = (0, react_1.useState)(null);
const [error, setError] = (0, react_1.useState)(null);
const [state, dispatch] = (0, react_1.useReducer)(userAgentReducer, initState);
(0, react_1.useEffect)(() => {
function getUserAgentData() {
function getHighEntropyUAData() {
return __awaiter(this, void 0, void 0, function* () {
switch (params === null || params === void 0 ? void 0 : params.entropy) {
case HIGH_ENTROPY: {
if (params.hints === undefined) {
setError(new Error("Cannot have high entropy and no hints."));
return;
}
const data = yield getHighEntropyUserAgentData(params.hints);
if (data instanceof Error) {
setError(data);
break;
}
dispatch({ type: HIGH_ENTROPY, payload: data });
break;
try {
// check if the `navigator.userAgentData` object is available
if (navigator.userAgentData === undefined) {
setError(new Error("User-agent client hints API is undefined."));
return;
}
case LOW_ENTROPY: {
const data = getLowEntropyUserAgentData();
dispatch({ type: LOW_ENTROPY, payload: data });
break;
// check if the user has granted permission for the client hints
if (navigator.userAgentData.getHighEntropyValues === undefined) {
setError(new Error("Permission denied accessing user-agent data"));
return;
}
case undefined: {
const data = getLowEntropyUserAgentData();
dispatch({ type: LOW_ENTROPY, payload: data });
break;
}
default: {
setError(new Error("An unexpected case has been encountered."));
break;
}
// request the high entropy values
const agentData = yield navigator.userAgentData.getHighEntropyValues(hints);
setUserAgentData(agentData);
}
catch (err) {
setError(new Error("Failed to get user-agent data"));
}
});
}
void getUserAgentData();
}, [params === null || params === void 0 ? void 0 : params.entropy, params === null || params === void 0 ? void 0 : params.hints]);
if (error instanceof Error)
throw error;
return state;
getHighEntropyUAData();
}, [hints]);
return [userAgentData, error];
}
exports.useUserAgentData = useUserAgentData;
function getHighEntropyUserAgentData(hints) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
try {
const agentData = yield ((_a = navigator.userAgentData) === null || _a === void 0 ? void 0 : _a.getHighEntropyValues(hints));
if (agentData === undefined) {
return new Error("Could not return user-agent data.");
}
return agentData;
}
catch (err) {
if (!(err instanceof Error))
throw new Error("An unexpected error has occurred.");
if (err.name === "NotAllowedError") {
return new Error("Permission denied accessing user-agent data.");
}
return err;
}
});
}
function getLowEntropyUserAgentData() {
if (navigator.userAgentData === undefined)
throw new Error("Client does not have user-agent data.");
return;
return navigator.userAgentData.toJSON();
}
const initState = {};
function userAgentReducer(state, action) {
switch (action.type) {
case HIGH_ENTROPY: {
return Object.assign(Object.assign({}, state), action.payload);
}
case LOW_ENTROPY: {
return Object.assign(Object.assign({}, state), action.payload);
}
default:
throw new Error("An unexpected case has been reached.");
}
}

@@ -1,3 +0,2 @@

export { useUserAgentClientHints } from "./hooks/useUserAgentClientHints";
export { UADataValues, UALowEntropyJSON, Hint } from "./types";
export { useUserAgentData } from "./hooks/useUserAgentData";
//# sourceMappingURL=index.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useUserAgentClientHints = void 0;
var useUserAgentClientHints_1 = require("./hooks/useUserAgentClientHints");
Object.defineProperty(exports, "useUserAgentClientHints", { enumerable: true, get: function () { return useUserAgentClientHints_1.useUserAgentClientHints; } });
exports.useUserAgentData = void 0;
var useUserAgentData_1 = require("./hooks/useUserAgentData");
Object.defineProperty(exports, "useUserAgentData", { enumerable: true, get: function () { return useUserAgentData_1.useUserAgentData; } });
{
"name": "react-user-agent-client-hints",
"version": "0.2.1",
"version": "0.2.2",
"description": "",

@@ -21,4 +21,5 @@ "main": "./dist/index.js",

"@jest/types": "^28.1.0",
"@playwright/test": "^1.29.2",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/react": "^13.4.0",
"@types/jest": "^27.5.1",

@@ -25,0 +26,0 @@ "@types/node": "^17.0.34",

@@ -7,4 +7,67 @@ # React User Agent Client Hints

![workflow](https://github.com/zakarynichols/react-user-agent-client-hints/actions/workflows/ci-cd.yml/badge.svg?branch=develop)
![example workflow](https://github.com/zakarynichols/react-user-agent-client-hints/actions/workflows/ci-cd.yml/badge.svg?branch=develop)
The useUserAgentData hook allows you to fetch high entropy user-agent data from the browser. It returns an object with the user-agent data, or an error if something went wrong.
## Usage
To use the useUserAgentData hook, you must pass an array of hints as an argument. These hints are used to request specific user-agent data.
```tsx
import { useUserAgentData } from "path/to/hook"
function MyComponent() {
const [userAgentData, error] = useUserAgentData(["brand", "version"])
if (error) {
return <div>{error.message}</div>
}
if (!userAgentData) {
return <div>Loading...</div>
}
return (
<div>
<p>Brands: {userAgentData.brands.map(brand => brand.brand).join(", ")}</p>
<p>Mobile: {userAgentData.mobile ? "Yes" : "No"}</p>
<p>Architecture: {userAgentData.architecture}</p>
<p>Bitness: {userAgentData.bitness}</p>
<p>Model: {userAgentData.model}</p>
<p>Platform: {userAgentData.platform}</p>
<p>Platform Version: {userAgentData.platformVersion}</p>
<p>UA Full Version: {userAgentData.uaFullVersion}</p>
<p>Wow64: {userAgentData.wow64 ? "Yes" : "No"}</p>
<p>
Full Version List:{" "}
{userAgentData.fullVersionList.map(brand => brand.brand).join(", ")}
</p>
</div>
)
}
```
```ts
interface UADataValues {
brands: NavigatorUABrandVersion[]
mobile: boolean
architecture: string
bitness: string
model: string
platform: string
platformVersion: string
uaFullVersion: string
wow64: boolean
fullVersionList: NavigatorUABrandVersion[]
}
```
## Error handling
If there is an error while fetching the user-agent data, useUserAgentData will return an error object with a message. The possible error messages are:
- User-agent client hints API is undefined.: The navigator.userAgentData object is not defined in the browser.
- Permission denied accessing user-agent data: The user has not granted permission for the client hints.
- Failed to get user-agent data: An unexpected error occurred.
### Potential Use Cases

@@ -21,40 +84,13 @@

### Installation
## Possible Hints
```sh
$ npm install react-user-agent-client-hints
```
- "brand": The brand of the user agent, such as "Google", "Apple", "Mozilla", etc.
- "model": The model of the device, such as "iPhone", "Pixel", "Galaxy", etc.
- "version": The version of the user agent, such as "13.0", "11.0", "78.0", etc.
- "architecture": The architecture of the device, such as "arm", "x86", "x86_64", etc.
- "platform": The platform the user agent is running on, such as "Windows", "macOS", "iOS", "Android", etc.
- "mobile": A boolean indicating whether the device is a mobile device or not.
- "fullVersionList": A list of objects representing the full version of the user agent and the brand
- "wow64": A boolean indicating whether the user agent is running on a 32-bit version of Windows on a 64-bit system.
### Examples
```ts
import { useUserAgentClientHints, Hint } from "react-user-agent-client-hints"
/** Declare in module scope or use `useMemo` if you need derived state. */
const hints = [
"architecture",
"model",
"bitness",
"platformVersion",
"fullVersionList"
]
/*
* High entropy potentially reveals more info about the operating
* system and browser. Under the hood is async allowing time for the
* browser to request user permission, or make other checks.
*/
const highEntropyUAData = useUserAgentClientHints({ entropy: "high", hints })
/*
* Low entropy runs sync, but potentially does not reveal enough information
* able to identify a user.
*/
const lowEntropyUAData = useUserAgentClientHints({ entropy: "low" })
/*
* Can call without parameters too.
*/
const UADataNoParams = useUserAgentClientHint()
```
### References

@@ -61,0 +97,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc