Skip to content

Commit

Permalink
Add descriptions to getters (useful in IDEs)
Browse files Browse the repository at this point in the history
  • Loading branch information
omrilotan committed Jul 9, 2024
1 parent 28341d9 commit 615298b
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change Log

# 2.2.1

- Add descriptions to getters (useful in IDEs).

# 2.2.0

- Add hints: "bitness", "prefersColorScheme", "prefersReducedMotion", "prefersReducedTransparency"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# client-hints [![](https://img.shields.io/npm/v/client-hints.svg?style=flat-square)](https://www.npmjs.com/package/client-hints)

🕵️‍♂️ Parse client hints headers
🕵️‍♂️ Parse client hints headers and provide a convenient API to access device information and user preferences

Use client hints, where available

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"name": "client-hints",
"version": "2.2.0",
"description": "🕵️‍♂️ Parse client hints headers",
"version": "2.2.1",
"description": "🕵️‍♂️ Parse client hints headers and provide a convenient API to access device information and user preferences",
"keywords": [
"client-hints",
"headers",
"sec-ch",
"🕵️‍♂️"
],
"author": "omrilotan <[email protected]> (https://omrilotan.com/)",
Expand Down
95 changes: 95 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ const HEADERS: Record<string, string> = {
WIDTH: "width",
};

/**
* Parse client hints headers and provide a convenient API to access device information and user preferences
*/
export class ClientHints {
entries: [string, string][];
constructor(input: Request | Headers | object) {
Expand Down Expand Up @@ -82,6 +85,11 @@ export class ClientHints {
return this.#store.get("uaVendorsList");
}

/**
* Convert to a JSONable object. Also used in the implementation of JSON.stringify
* @example
* console.log(new ClientHints(request)) // {"mobile":true,"vendorName":"Chrome","vendorVersion":"91",...}
*/
toJSON(): Record<string, string | number | boolean> {
return Object.getOwnPropertyNames(Object.getPrototypeOf(this))
.filter((name) => name !== "constructor")
Expand All @@ -92,18 +100,27 @@ export class ClientHints {
);
}

/**
* The browser is on a mobile device
*/
get mobile(): boolean | undefined {
const value = this.#get(HEADERS.MOBILE);
return value ? value.includes("?1") : undefined;
}

/**
* Browser brand name
*/
get vendorName(): string | undefined {
const names = this.#uaVendorsList
.map(({ name }) => name)
.filter((name) => !/^[\W]*not/i.test(name));
return vendors.find((vendor) => names.includes(vendor)) ?? names.at(0);
}

/**
* Browser version
*/
get vendorVersion(): string | undefined {
const header = this.#get(HEADERS.USER_AGENT_VERSION);
if (header) {
Expand All @@ -115,95 +132,164 @@ export class ClientHints {
return entry?.v || entry?.version || undefined;
}

/**
* Operating system name
*/
get platform(): string | undefined {
return parse(this.#get(HEADERS.USER_AGENT_PLATFORM));
}

/**
* Operating system version
*/
get platformVersion(): string | undefined {
return parse(this.#get(HEADERS.USER_AGENT_PLATFORM_VERSION));
}

/**
* Relationship to origin
*/
get fetchSite(): string | undefined {
return parse(this.#get(HEADERS.FETCH_SITE));
}

/**
* Navigation type (navigate, nested-navigate, same-origin, cross-origin, ...)
*/
get fetchMode(): string | undefined {
return parse(this.#get(HEADERS.FETCH_MODE));
}

/**
* Resource type (document, iframe, script, image, ...)
*/
get fetchDest(): string | undefined {
return parse(this.#get(HEADERS.FETCH_DEST));
}

/**
* Resource type (document, iframe, script, image, ...)
*/
get fetchDestination(): string | undefined {
return parse(this.#get(HEADERS.FETCH_DEST));
}

/**
* User activation
*/
get fetchUser(): boolean | undefined {
const value = this.#get(HEADERS.FETCH_USER);
return value ? value.includes("?1") : undefined;
}

/**
* CPU architecture (ARM, x86)
*/
get arch(): string | undefined {
return parse(this.#get(HEADERS.USER_AGENT_ARCH));
}

/**
* CPU architecture (ARM, x86)
*/
get architecture(): string | undefined {
return parse(this.#get(HEADERS.USER_AGENT_ARCH));
}

/**
* CPU bitness (32, 64)
*/
get bitness(): number | undefined {
return toNumber(parse(this.#get(HEADERS.BITNESS)));
}

/**
* Device model name
*/
get model(): string | undefined {
return parse(this.#get(HEADERS.USER_AGENT_MODEL));
}

/**
* Device amount of RAM (approximate)
*/
get deviceMemory(): number | undefined {
return toNumber(parse(this.#get(HEADERS.DEVICE_MEMORY)));
}

/**
* [Deprecated] Image density suitable for the screen
*/
get contentDevicePixelRatio(): number | undefined {
return toNumber(parse(this.#get(HEADERS.CONTENT_DPR)));
}

/**
* [Deprecated] Image density suitable for the screen
*/
get contentDpr(): number | undefined {
return toNumber(parse(this.#get(HEADERS.CONTENT_DPR)));
}

/**
* [Deprecated] Screen pixel density
*/
get devicePixelRatio(): number | undefined {
return toNumber(parse(this.#get(HEADERS.DPR)));
}

/**
* [Deprecated] Screen pixel density
*/
get dpr(): number | undefined {
return toNumber(parse(this.#get(HEADERS.DPR)));
}

/**
* Connection type name (slow-2g, 2g, 3g, 4g, ...)
*/
get effectiveConnectionType(): string | undefined {
return parse(this.#get(HEADERS.ECT));
}

/**
* Connection type name (slow-2g, 2g, 3g, 4g, ...)
*/
get ect(): string | undefined {
return parse(this.#get(HEADERS.ECT));
}

/**
* Approximate bandwidth of the connection
*/
get downlink(): number | undefined {
return toNumber(parse(this.#get(HEADERS.DOWNLINK)));
}

/**
* [Deprecated] Screen width in pixels
*/
get width(): number | undefined {
return toNumber(parse(this.#get(HEADERS.WIDTH)));
}

/**
* [Deprecated] Viewport width in pixels
*/
get viewportWidth(): number | undefined {
return toNumber(parse(this.#get(HEADERS.VIEWPORT_WIDTH)));
}

/**
* Accesibility; Preferred color scheme (light, dark)
*/
get prefersColorScheme(): "light" | "dark" | undefined {
return parse(this.#get(HEADERS.PREFERS_COLOR_SCHEME));
}

/**
* Accesibility; Preferred reduced motion setting
*/
get prefersReducedMotion(): boolean | undefined {
switch (this.#get(HEADERS.PREFERS_REDUCED_MOTION)) {
case "no-preference":
Expand All @@ -215,6 +301,9 @@ export class ClientHints {
}
}

/**
* Accesibility; Preferred reduced transparency setting
*/
get prefersReducedTransparency(): boolean | undefined {
switch (this.#get(HEADERS.PREFERS_REDUCED_TRANSPARENCY)) {
case "no-preference":
Expand All @@ -226,10 +315,16 @@ export class ClientHints {
}
}

/**
* Purpose of the request (prefetch, ...)
*/
get purpose(): string | undefined {
return parse(this.#get(HEADERS.PURPOSE));
}

/**
* [Non-standard] Global privacy control (GPC) setting
*/
get gpc(): boolean | undefined {
const value = this.#get(HEADERS.GPC);
return value ? value === "1" : undefined;
Expand Down

0 comments on commit 615298b

Please sign in to comment.