From a3a7a5e377146a5a349a912f04c6da82cc3e82e1 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Tue, 14 Oct 2025 12:28:36 +0700 Subject: [PATCH] Break some methods in `helpers` as new submodules: `bot-detection`, `browser-detection`, `device-detection` `isAIBot()` & `isBot()` => `bot-detection` `isChromeFamily()`, `isElectron()`, `isFromEU()`, & `isStandalonePWA()` => `browser-detection` `getDeviceVendor()` & `isAppleSilicon()` => `device-detection` --- package.json | 15 ++ script/build-esm.js | 18 ++ src/bot-detection/bot-detection.d.ts | 6 + src/bot-detection/bot-detection.js | 125 ++++++++++++ src/bot-detection/bot-detection.mjs | 129 +++++++++++++ src/browser-detection/browser-detection.d.ts | 10 + src/browser-detection/browser-detection.js | 28 +++ src/browser-detection/browser-detection.mjs | 30 +++ src/device-detection/device-detection.d.ts | 8 + src/device-detection/device-detection.js | 43 +++++ src/device-detection/device-detection.mjs | 47 +++++ src/helpers/ua-parser-helpers.d.ts | 41 +++- src/helpers/ua-parser-helpers.js | 192 ++++--------------- src/helpers/ua-parser-helpers.mjs | 172 ++--------------- 14 files changed, 550 insertions(+), 314 deletions(-) create mode 100644 src/bot-detection/bot-detection.d.ts create mode 100644 src/bot-detection/bot-detection.js create mode 100644 src/bot-detection/bot-detection.mjs create mode 100644 src/browser-detection/browser-detection.d.ts create mode 100644 src/browser-detection/browser-detection.js create mode 100644 src/browser-detection/browser-detection.mjs create mode 100644 src/device-detection/device-detection.d.ts create mode 100644 src/device-detection/device-detection.js create mode 100644 src/device-detection/device-detection.mjs diff --git a/package.json b/package.json index b39ab3c..156aa02 100755 --- a/package.json +++ b/package.json @@ -190,6 +190,21 @@ "import": "./src/main/ua-parser.mjs", "types": "./src/main/ua-parser.d.ts" }, + "./bot-detection": { + "require": "./src/bot-detection/bot-detection.js", + "import": "./src/bot-detection/bot-detection.mjs", + "types": "./src/bot-detection/bot-detection.d.ts" + }, + "./browser-detection": { + "require": "./src/browser-detection/browser-detection.js", + "import": "./src/browser-detection/browser-detection.mjs", + "types": "./src/browser-detection/browser-detection.d.ts" + }, + "./device-detection": { + "require": "./src/device-detection/device-detection.js", + "import": "./src/device-detection/device-detection.mjs", + "types": "./src/device-detection/device-detection.d.ts" + }, "./enums": { "require": "./src/enums/ua-parser-enums.js", "import": "./src/enums/ua-parser-enums.mjs", diff --git a/script/build-esm.js b/script/build-esm.js index 78321dd..89f390b 100755 --- a/script/build-esm.js +++ b/script/build-esm.js @@ -40,6 +40,24 @@ const files = [ ...defaultReplacements.mjs ] }, + { + src : 'src/bot-detection/bot-detection.js', + dest :'src/bot-detection/bot-detection.mjs', + title : 'Generated ESM version of ua-parser-js/bot-detection', + replacements : [...defaultReplacements.mjs] + }, + { + src : 'src/browser-detection/browser-detection.js', + dest :'src/browser-detection/browser-detection.mjs', + title : 'Generated ESM version of ua-parser-js/browser-detection', + replacements : [...defaultReplacements.mjs] + }, + { + src : 'src/device-detection/device-detection.js', + dest :'src/device-detection/device-detection.mjs', + title : 'Generated ESM version of ua-parser-js/device-detection', + replacements : [...defaultReplacements.mjs] + }, { src : 'src/enums/ua-parser-enums.js', dest :'src/enums/ua-parser-enums.mjs', diff --git a/src/bot-detection/bot-detection.d.ts b/src/bot-detection/bot-detection.d.ts new file mode 100644 index 0000000..f0eb012 --- /dev/null +++ b/src/bot-detection/bot-detection.d.ts @@ -0,0 +1,6 @@ +// Type definitions for bot-detection submodule of UAParser.js v2.0.7 +// Project: https://github.com/faisalman/ua-parser-js +// Definitions by: Faisal Salman + +export function isAICrawler(ua: string): boolean; +export function isBot(ua: string): boolean; \ No newline at end of file diff --git a/src/bot-detection/bot-detection.js b/src/bot-detection/bot-detection.js new file mode 100644 index 0000000..36a42a8 --- /dev/null +++ b/src/bot-detection/bot-detection.js @@ -0,0 +1,125 @@ +////////////////////////////////////////////////// +/* bot-detection submodule of UAParser.js v2.0.7 + https://github.com/faisalman/ua-parser-js + Author: Faisal Salman + AGPLv3 License */ +///////////////////////////////////////////////// + +/*jshint esversion: 6 */ + +const { UAParser } = require('../main/ua-parser'); +const { Extension, BrowserType } = require('../enums/ua-parser-enums'); +const { Bots, Crawlers } = require('../extensions/ua-parser-extensions'); +const { Crawler } = Extension.BrowserName; + +const BotTypesList = [ + BrowserType.CLI, + BrowserType.CRAWLER, + BrowserType.FETCHER, + BrowserType.LIBRARY +]; + +const AICrawlersList = [ + // AI2 + Crawler.AI2_BOT, + // Amazon + Crawler.AMAZON_BOT, + // Anthropic + Crawler.ANTHROPIC_AI, + Crawler.ANTHROPIC_CLAUDE_BOT, + Crawler.ANTHROPIC_CLAUDE_SEARCHBOT, + Crawler.ANTHROPIC_CLAUDE_WEB, + // Apple + Crawler.APPLE_BOT, + Crawler.APPLE_BOT_EXTENDED, + // Brave + Crawler.BRAVE_BOT, + // ByteDance + Crawler.BYTEDANCE_BYTESPIDER, + Crawler.BYTEDANCE_TIKTOKSPIDER, + // Cohere + Crawler.COHERE_TRAINING_DATA_CRAWLER, + // Common Crawl + Crawler.COMMON_CRAWL_CCBOT, + // Coveo + Crawler.COVEO_BOT, + // DataForSeo + Crawler.DATAFORSEO_BOT, + // DeepSeek + Crawler.DEEPSEEK_BOT, + // Diffbot + Crawler.DIFFBOT, + // Google + Crawler.GOOGLE_EXTENDED, + Crawler.GOOGLE_OTHER, + Crawler.GOOGLE_OTHER_IMAGE, + Crawler.GOOGLE_OTHER_VIDEO, + Crawler.GOOGLE_CLOUDVERTEXBOT, + // Hive AI + Crawler.HIVE_IMAGESIFTBOT, + // Huawei + Crawler.HUAWEI_PETALBOT, + Crawler.HUAWEI_PANGUBOT, + // Hugging Face + Crawler.HUGGINGFACE_BOT, + // Kangaroo + Crawler.KANGAROO_BOT, + // Mendable.ai + Crawler.FIRECRAWL_AGENT, + // Meta + Crawler.META_FACEBOOKBOT, + Crawler.META_EXTERNALAGENT, + // OpenAI + Crawler.OPENAI_GPTBOT, + Crawler.OPENAI_SEARCH_BOT, + // Perplexity + Crawler.PERPLEXITY_BOT, + // Replicate + Crawler.REPLICATE_BOT, + // Runpod + Crawler.RUNPOD_BOT, + // SB Intuitions + Crawler.SB_INTUITIONS_BOT, + // Semrush + Crawler.SEMRUSH_BOT_CONTENTSHAKE, + // Timpi + Crawler.TIMPI_BOT, + // Together AI + Crawler.TOGETHER_BOT, + // Velen.io + Crawler.HUNTER_VELENPUBLICWEBCRAWLER, + // Vercel + Crawler.VERCEL_V0BOT, + // Webz.io + Crawler.WEBZIO_OMGILI, + Crawler.WEBZIO_OMGILI_BOT, + Crawler.WEBZIO_EXTENDED, + // X + Crawler.XAI_BOT, + // You.com + Crawler.YOU_BOT, + // Zhipu AI + Crawler.ZHIPU_CHATGLM_SPIDER +]; + +const isAICrawler = ua => + AICrawlersList + .map(s=>s.toLowerCase()) + .includes( + (typeof ua === 'string' ? + new UAParser(ua, Crawlers).getBrowser() : + ua.browser + ).name?.toLowerCase()); + +const isBot = ua => + BotTypesList + .includes( + (typeof ua === 'string' ? + new UAParser(ua, Bots).getBrowser() : + ua.browser + ).type); + +module.exports = { + isAICrawler, + isBot +} \ No newline at end of file diff --git a/src/bot-detection/bot-detection.mjs b/src/bot-detection/bot-detection.mjs new file mode 100644 index 0000000..67818ef --- /dev/null +++ b/src/bot-detection/bot-detection.mjs @@ -0,0 +1,129 @@ +// Generated ESM version of ua-parser-js/bot-detection +// DO NOT EDIT THIS FILE! +// Source: /src/bot-detection/bot-detection.js + +////////////////////////////////////////////////// +/* bot-detection submodule of UAParser.js v2.0.7 + https://github.com/faisalman/ua-parser-js + Author: Faisal Salman + AGPLv3 License */ +///////////////////////////////////////////////// + +/*jshint esversion: 6 */ + +import { UAParser } from '../main/ua-parser.mjs'; +import { Extension, BrowserType } from '../enums/ua-parser-enums.mjs'; +import { Bots, Crawlers, Fetchers } from '../extensions/ua-parser-extensions.mjs'; +const { Crawler } = Extension.BrowserName; + +const BotTypesList = [ + BrowserType.CLI, + BrowserType.CRAWLER, + BrowserType.FETCHER, + BrowserType.LIBRARY +]; + +const AICrawlersList = [ + // AI2 + Crawler.AI2_BOT, + // Amazon + Crawler.AMAZON_BOT, + // Anthropic + Crawler.ANTHROPIC_AI, + Crawler.ANTHROPIC_CLAUDE_BOT, + Crawler.ANTHROPIC_CLAUDE_SEARCHBOT, + Crawler.ANTHROPIC_CLAUDE_WEB, + // Apple + Crawler.APPLE_BOT, + Crawler.APPLE_BOT_EXTENDED, + // Brave + Crawler.BRAVE_BOT, + // ByteDance + Crawler.BYTEDANCE_BYTESPIDER, + Crawler.BYTEDANCE_TIKTOKSPIDER, + // Cohere + Crawler.COHERE_TRAINING_DATA_CRAWLER, + // Common Crawl + Crawler.COMMON_CRAWL_CCBOT, + // Coveo + Crawler.COVEO_BOT, + // DataForSeo + Crawler.DATAFORSEO_BOT, + // DeepSeek + Crawler.DEEPSEEK_BOT, + // Diffbot + Crawler.DIFFBOT, + // Google + Crawler.GOOGLE_EXTENDED, + Crawler.GOOGLE_OTHER, + Crawler.GOOGLE_OTHER_IMAGE, + Crawler.GOOGLE_OTHER_VIDEO, + Crawler.GOOGLE_CLOUDVERTEXBOT, + // Hive AI + Crawler.HIVE_IMAGESIFTBOT, + // Huawei + Crawler.HUAWEI_PETALBOT, + Crawler.HUAWEI_PANGUBOT, + // Hugging Face + Crawler.HUGGINGFACE_BOT, + // Kangaroo + Crawler.KANGAROO_BOT, + // Mendable.ai + Crawler.FIRECRAWL_AGENT, + // Meta + Crawler.META_FACEBOOKBOT, + Crawler.META_EXTERNALAGENT, + // OpenAI + Crawler.OPENAI_GPTBOT, + Crawler.OPENAI_SEARCH_BOT, + // Perplexity + Crawler.PERPLEXITY_BOT, + // Replicate + Crawler.REPLICATE_BOT, + // Runpod + Crawler.RUNPOD_BOT, + // SB Intuitions + Crawler.SB_INTUITIONS_BOT, + // Semrush + Crawler.SEMRUSH_BOT_CONTENTSHAKE, + // Timpi + Crawler.TIMPI_BOT, + // Together AI + Crawler.TOGETHER_BOT, + // Velen.io + Crawler.HUNTER_VELENPUBLICWEBCRAWLER, + // Vercel + Crawler.VERCEL_V0BOT, + // Webz.io + Crawler.WEBZIO_OMGILI, + Crawler.WEBZIO_OMGILI_BOT, + Crawler.WEBZIO_EXTENDED, + // X + Crawler.XAI_BOT, + // You.com + Crawler.YOU_BOT, + // Zhipu AI + Crawler.ZHIPU_CHATGLM_SPIDER +]; + +const isAICrawler = ua => + AICrawlersList + .map(s=>s.toLowerCase()) + .includes( + (typeof ua === 'string' ? + new UAParser(ua, Crawlers).getBrowser() : + ua.browser + ).name?.toLowerCase()); + +const isBot = ua => + BotTypesList + .includes( + (typeof ua === 'string' ? + new UAParser(ua, Bots).getBrowser() : + ua.browser + ).type); + +export { + isAICrawler, + isBot +} \ No newline at end of file diff --git a/src/browser-detection/browser-detection.d.ts b/src/browser-detection/browser-detection.d.ts new file mode 100644 index 0000000..32df346 --- /dev/null +++ b/src/browser-detection/browser-detection.d.ts @@ -0,0 +1,10 @@ +// Type definitions for browser-detection submodule of UAParser.js v2.0.7 +// Project: https://github.com/faisalman/ua-parser-js +// Definitions by: Faisal Salman + +import type { IResult } from "../main/ua-parser"; + +export function isChromeFamily(resultOrUA: IResult | string): boolean; +export function isElectron(): boolean; +export function isFromEU(): boolean; +export function isStandalonePWA(): boolean; \ No newline at end of file diff --git a/src/browser-detection/browser-detection.js b/src/browser-detection/browser-detection.js new file mode 100644 index 0000000..0f01ecf --- /dev/null +++ b/src/browser-detection/browser-detection.js @@ -0,0 +1,28 @@ +////////////////////////////////////////////////////// +/* browser-detection submodule of UAParser.js v2.0.7 + https://github.com/faisalman/ua-parser-js + Author: Faisal Salman + AGPLv3 License */ +///////////////////////////////////////////////////// + +/*jshint esversion: 6 */ + +const { UAParser } = require('../main/ua-parser'); +const { isStandalonePWA } = require('is-standalone-pwa'); +const { isFromEU } = require('detect-europe-js'); + +const isChromeFamily = val => !!( + (typeof val === 'string' ? + new UAParser(val).getEngine() : + val.engine + )?.is(EngineName.BLINK)); + +const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js + / electron\//i.test(navigator?.userAgent)); // browser + +module.exports = { + isChromeFamily, + isElectron, + isFromEU, + isStandalonePWA +} \ No newline at end of file diff --git a/src/browser-detection/browser-detection.mjs b/src/browser-detection/browser-detection.mjs new file mode 100644 index 0000000..eeb6c0e --- /dev/null +++ b/src/browser-detection/browser-detection.mjs @@ -0,0 +1,30 @@ +// Generated ESM version of ua-parser-js/browser-detection +// DO NOT EDIT THIS FILE! +// Source: /src/browser-detection/browser-detection.js + +////////////////////////////////////////////////////// +/* browser-detection submodule of UAParser.js v2.0.7 + https://github.com/faisalman/ua-parser-js + Author: Faisal Salman + AGPLv3 License */ +///////////////////////////////////////////////////// + +/*jshint esversion: 6 */ + +import { UAParser } from '../main/ua-parser.mjs'; +import { isStandalonePWA } from 'is-standalone-pwa'; + +const isChromeFamily = val => !!( + (typeof val === 'string' ? + new UAParser(val).getEngine() : + val.engine + )?.is(EngineName.BLINK)); + +const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js + / electron\//i.test(navigator?.userAgent)); // browser + +export { + isChromeFamily, + isElectron, + isStandalonePWA +} \ No newline at end of file diff --git a/src/device-detection/device-detection.d.ts b/src/device-detection/device-detection.d.ts new file mode 100644 index 0000000..0f92714 --- /dev/null +++ b/src/device-detection/device-detection.d.ts @@ -0,0 +1,8 @@ +// Type definitions for device-detection submodule of UAParser.js v2.0.7 +// Project: https://github.com/faisalman/ua-parser-js +// Definitions by: Faisal Salman + +import type { IResult } from "../main/ua-parser"; + +export function getDeviceVendor(model: string): string | undefined; +export function isAppleSilicon(resultOrUA: IResult | string): boolean; \ No newline at end of file diff --git a/src/device-detection/device-detection.js b/src/device-detection/device-detection.js new file mode 100644 index 0000000..2be90f1 --- /dev/null +++ b/src/device-detection/device-detection.js @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////// +/* device-detection submodule of UAParser.js v2.0.7 + https://github.com/faisalman/ua-parser-js + Author: Faisal Salman + AGPLv3 License */ +//////////////////////////////////////////////////// + +/*jshint esversion: 6 */ + +const { UAParser } = require('../main/ua-parser'); +const { CPUArch, OSName } = require('../enums/ua-parser-enums'); + +const getDeviceVendor = (model) => new UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).getDevice().vendor; + +const isAppleSilicon = (val) => { + const { os, cpu } = typeof val !== 'string' ? val : { + os: new UAParser(val).getOS(), + cpu: new UAParser(val).getCPU() + }; + if (os.is(OSName.MACOS)) { + if (cpu.is(CPUArch.ARM)) { + return true; + } else if (typeof window !== 'undefined') { + try { + const canvas = document.createElement('canvas'); + const webgl = canvas.getContext('webgl2') || + canvas.getContext('webgl') || + canvas.getContext('experimental-webgl'); + return webgl + .getParameter(webgl.getExtension('WEBGL_debug_renderer_info').UNMASKED_RENDERER_WEBGL) + .match(/apple m\d/i); + } catch { + return false; + } + } + } + return false; +} + +module.exports = { + getDeviceVendor, + isAppleSilicon +} \ No newline at end of file diff --git a/src/device-detection/device-detection.mjs b/src/device-detection/device-detection.mjs new file mode 100644 index 0000000..c66a3a7 --- /dev/null +++ b/src/device-detection/device-detection.mjs @@ -0,0 +1,47 @@ +// Generated ESM version of ua-parser-js/device-detection +// DO NOT EDIT THIS FILE! +// Source: /src/device-detection/device-detection.js + +///////////////////////////////////////////////////// +/* device-detection submodule of UAParser.js v2.0.7 + https://github.com/faisalman/ua-parser-js + Author: Faisal Salman + AGPLv3 License */ +//////////////////////////////////////////////////// + +/*jshint esversion: 6 */ + +import { UAParser } from '../main/ua-parser.mjs'; +import { CPUArch, OSName } from '../enums/ua-parser-enums.mjs'; + +const getDeviceVendor = (model) => new UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).getDevice().vendor; + +const isAppleSilicon = (val) => { + const { os, cpu } = typeof val !== 'string' ? val : { + os: new UAParser(val).getOS(), + cpu: new UAParser(val).getCPU() + }; + if (os.is(OSName.MACOS)) { + if (cpu.is(CPUArch.ARM)) { + return true; + } else if (typeof window !== 'undefined') { + try { + const canvas = document.createElement('canvas'); + const webgl = canvas.getContext('webgl2') || + canvas.getContext('webgl') || + canvas.getContext('experimental-webgl'); + return webgl + .getParameter(webgl.getExtension('WEBGL_debug_renderer_info').UNMASKED_RENDERER_WEBGL) + .match(/apple m\d/i); + } catch { + return false; + } + } + } + return false; +} + +export { + getDeviceVendor, + isAppleSilicon +} \ No newline at end of file diff --git a/src/helpers/ua-parser-helpers.d.ts b/src/helpers/ua-parser-helpers.d.ts index caee9cb..0cbeea0 100644 --- a/src/helpers/ua-parser-helpers.d.ts +++ b/src/helpers/ua-parser-helpers.d.ts @@ -4,12 +4,37 @@ import type { IResult } from "../main/ua-parser"; -export function getDeviceVendor(model: string): string | undefined; -export function isAppleSilicon(resultOrUA: IResult | string): boolean; -export function isAIBot(resultOrUA: IResult | string): boolean; -export function isBot(resultOrUA: IResult | string): boolean; -export function isChromeFamily(resultOrUA: IResult | string): boolean; -export function isElectron(): boolean; -export function isFromEU(): boolean; export function isFrozenUA(ua: string): boolean; -export function isStandalonePWA(): boolean; + +/** + * @deprecated Moved to `device-detection` submodule + */ +export function getDeviceVendor(model: string): string | undefined; +/** + * @deprecated Moved to `device-detection` submodule + */ +export function isAppleSilicon(resultOrUA: IResult | string): boolean; +/** + * @deprecated Moved to `bot-detection` submodule + */ +export function isAIBot(resultOrUA: IResult | string): boolean; +/** + * @deprecated Moved to `bot-detection` submodule + */ +export function isBot(resultOrUA: IResult | string): boolean; +/** + * @deprecated Moved to `browser-detection` submodule + */ +export function isChromeFamily(resultOrUA: IResult | string): boolean; +/** + * @deprecated Moved to `browser-detection` submodule + */ +export function isElectron(): boolean; +/** + * @deprecated Moved to `browser-detection` submodule + */ +export function isFromEU(): boolean; +/** + * @deprecated Moved to `browser-detection` submodule + */ +export function isStandalonePWA(): boolean; \ No newline at end of file diff --git a/src/helpers/ua-parser-helpers.js b/src/helpers/ua-parser-helpers.js index 08975ba..8a0214e 100644 --- a/src/helpers/ua-parser-helpers.js +++ b/src/helpers/ua-parser-helpers.js @@ -8,170 +8,54 @@ /*jshint esversion: 6 */ const { UAParser } = require('../main/ua-parser'); -const { CPUArch, OSName, EngineName, Extension, BrowserType } = require('../enums/ua-parser-enums'); -const { Bots, Crawlers } = require('../extensions/ua-parser-extensions'); -const { isFromEU } = require('detect-europe-js'); +const { EngineName } = require('../enums/ua-parser-enums'); +const { getDeviceVendor: _getDeviceVendor, isAppleSilicon: _isAppleSilicon } = require('../device-detection/device-detection'); +const { isBot: _isBot, isAICrawler } = require('../bot-detection/bot-detection'); +const { isStandalonePWA: _isStandalonePWA } = require('../browser-detection/browser-detection'); +const { isFromEU: _isFromEU } = require('../browser-detection/browser-detection'); const { isFrozenUA } = require('ua-is-frozen'); -const { isStandalonePWA } = require('is-standalone-pwa'); -const { Crawler } = Extension.BrowserName; -const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value; +/** + * @deprecated Moved to `device-detection` submodule + */ +const getDeviceVendor = _getDeviceVendor; -const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor; +/** + * @deprecated Moved to `device-detection` submodule + */ +const isAppleSilicon = _isAppleSilicon; -const isAppleSilicon = (resultOrUA) => { - const res = toResult(resultOrUA); - if (res.os.is(OSName.MACOS)) { - if (res.cpu.is(CPUArch.ARM)) { - return true; - } - if (typeof resultOrUA !== 'string' && typeof window !== 'undefined') { - try { - const canvas = document.createElement('canvas'); - const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); - const debug = webgl.getExtension('WEBGL_debug_renderer_info'); - const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL); - if (renderer.match(/apple m\d/i)) { - return true; - } - } catch { - return false; - } - } - } - return false; -} +/** + * @deprecated Moved to `bot-detection` submodule + */ +const isAIBot = isAICrawler; -const isAIBot = (resultOrUA) => [ +/** + * @deprecated Moved to `bot-detection` submodule + */ +const isBot = _isBot; - // AI2 - Crawler.AI2_BOT, - - // Amazon - Crawler.AMAZON_BOT, - - // Anthropic - Crawler.ANTHROPIC_AI, - Crawler.ANTHROPIC_CLAUDE_BOT, - Crawler.ANTHROPIC_CLAUDE_SEARCHBOT, - Crawler.ANTHROPIC_CLAUDE_WEB, - - // Apple - Crawler.APPLE_BOT, - Crawler.APPLE_BOT_EXTENDED, - - // Brave - Crawler.BRAVE_BOT, - - // ByteDance - Crawler.BYTEDANCE_BYTESPIDER, - Crawler.BYTEDANCE_TIKTOKSPIDER, - - // Cohere - Crawler.COHERE_TRAINING_DATA_CRAWLER, - - // Common Crawl - Crawler.COMMON_CRAWL_CCBOT, - - // Coveo - Crawler.COVEO_BOT, - - // DataForSeo - Crawler.DATAFORSEO_BOT, - - // DeepSeek - Crawler.DEEPSEEK_BOT, - - // Diffbot - Crawler.DIFFBOT, - - // Google - Crawler.GOOGLE_EXTENDED, - Crawler.GOOGLE_OTHER, - Crawler.GOOGLE_OTHER_IMAGE, - Crawler.GOOGLE_OTHER_VIDEO, - Crawler.GOOGLE_CLOUDVERTEXBOT, - - // Hive AI - Crawler.HIVE_IMAGESIFTBOT, - - // Huawei - Crawler.HUAWEI_PETALBOT, - Crawler.HUAWEI_PANGUBOT, - - // Hugging Face - Crawler.HUGGINGFACE_BOT, - - // Kangaroo - Crawler.KANGAROO_BOT, - - // Mendable.ai - Crawler.FIRECRAWL_AGENT, - - // Meta - Crawler.META_FACEBOOKBOT, - Crawler.META_EXTERNALAGENT, - - // OpenAI - Crawler.OPENAI_GPTBOT, - Crawler.OPENAI_SEARCH_BOT, - - // Perplexity - Crawler.PERPLEXITY_BOT, - - // Replicate - Crawler.REPLICATE_BOT, - - // Runpod - Crawler.RUNPOD_BOT, - - // SB Intuitions - Crawler.SB_INTUITIONS_BOT, - - // Semrush - Crawler.SEMRUSH_BOT_CONTENTSHAKE, - - // Timpi - Crawler.TIMPI_BOT, - - // Together AI - Crawler.TOGETHER_BOT, - - // Velen.io - Crawler.HUNTER_VELENPUBLICWEBCRAWLER, - - // Vercel - Crawler.VERCEL_V0BOT, - - // Webz.io - Crawler.WEBZIO_OMGILI, - Crawler.WEBZIO_OMGILI_BOT, - Crawler.WEBZIO_EXTENDED, - - // X - Crawler.XAI_BOT, - - // You.com - Crawler.YOU_BOT, - - // Zhipu AI - Crawler.ZHIPU_CHATGLM_SPIDER - ] - .map((s) => s.toLowerCase()) - .includes(String(toResult(resultOrUA, Crawlers).browser.name).toLowerCase()); - -const isBot = (resultOrUA) => [ - BrowserType.CLI, - BrowserType.CRAWLER, - BrowserType.FETCHER, - BrowserType.LIBRARY - ].includes(toResult(resultOrUA, Bots).browser.type); - -const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(EngineName.BLINK); +/** + * @deprecated Moved to `browser-detection` submodule + */ +const isChromeFamily = val => !!((typeof val === 'string' ? new UAParser(val).getEngine() : val.engine)?.is(EngineName.BLINK)); +/** + * @deprecated Moved to `browser-detection` submodule + */ const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js / electron\//i.test(navigator?.userAgent)); // browser +/** + * @deprecated Moved to `browser-detection` submodule + */ +const isFromEU = _isFromEU; + +/** + * @deprecated Moved to `browser-detection` submodule + */ +const isStandalonePWA = _isStandalonePWA; + module.exports = { getDeviceVendor, isAppleSilicon, diff --git a/src/helpers/ua-parser-helpers.mjs b/src/helpers/ua-parser-helpers.mjs index 409de41..6d0d8ca 100644 --- a/src/helpers/ua-parser-helpers.mjs +++ b/src/helpers/ua-parser-helpers.mjs @@ -12,166 +12,34 @@ /*jshint esversion: 6 */ import { UAParser } from '../main/ua-parser.mjs'; -import { CPUArch, OSName, EngineName, Extension, BrowserType } from '../enums/ua-parser-enums.mjs'; -import { Bots, Crawlers } from '../extensions/ua-parser-extensions.mjs'; +import { EngineName } from '../enums/ua-parser-enums.mjs'; +import { getDeviceVendor: _getDeviceVendor, isAppleSilicon: _isAppleSilicon } from '../device-detection/device-detection.mjs'; +import { isBot: _isBot, isAICrawler } from '../bot-detection/bot-detection.mjs'; import { isFromEU } from 'detect-europe-js'; import { isFrozenUA } from 'ua-is-frozen'; import { isStandalonePWA } from 'is-standalone-pwa'; -const { Crawler } = Extension.BrowserName; -const toResult = (value, head, ext) => typeof value === 'string' ? UAParser(value, head, ext) : value; +/** + * @deprecated Moved to `device-detection` submodule + */ +const getDeviceVendor = _getDeviceVendor; -const getDeviceVendor = (model) => UAParser(`Mozilla/5.0 (Linux; Android 10; ${model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36`).device.vendor; +/** + * @deprecated Moved to `device-detection` submodule + */ +const isAppleSilicon = _isAppleSilicon; -const isAppleSilicon = (resultOrUA) => { - const res = toResult(resultOrUA); - if (res.os.is(OSName.MACOS)) { - if (res.cpu.is(CPUArch.ARM)) { - return true; - } - if (typeof resultOrUA !== 'string' && typeof window !== 'undefined') { - try { - const canvas = document.createElement('canvas'); - const webgl = canvas.getContext('webgl2') || canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); - const debug = webgl.getExtension('WEBGL_debug_renderer_info'); - const renderer = webgl.getParameter(debug.UNMASKED_RENDERER_WEBGL); - if (renderer.match(/apple m\d/i)) { - return true; - } - } catch { - return false; - } - } - } - return false; -} +/** + * @deprecated Moved to `bot-detection` submodule + */ +const isAIBot = isAICrawler; -const isAIBot = (resultOrUA) => [ +/** + * @deprecated Moved to `bot-detection` submodule + */ +const isBot = _isBot; - // AI2 - Crawler.AI2_BOT, - - // Amazon - Crawler.AMAZON_BOT, - - // Anthropic - Crawler.ANTHROPIC_AI, - Crawler.ANTHROPIC_CLAUDE_BOT, - Crawler.ANTHROPIC_CLAUDE_SEARCHBOT, - Crawler.ANTHROPIC_CLAUDE_WEB, - - // Apple - Crawler.APPLE_BOT, - Crawler.APPLE_BOT_EXTENDED, - - // Brave - Crawler.BRAVE_BOT, - - // ByteDance - Crawler.BYTEDANCE_BYTESPIDER, - Crawler.BYTEDANCE_TIKTOKSPIDER, - - // Cohere - Crawler.COHERE_TRAINING_DATA_CRAWLER, - - // Common Crawl - Crawler.COMMON_CRAWL_CCBOT, - - // Coveo - Crawler.COVEO_BOT, - - // DataForSeo - Crawler.DATAFORSEO_BOT, - - // DeepSeek - Crawler.DEEPSEEK_BOT, - - // Diffbot - Crawler.DIFFBOT, - - // Google - Crawler.GOOGLE_EXTENDED, - Crawler.GOOGLE_OTHER, - Crawler.GOOGLE_OTHER_IMAGE, - Crawler.GOOGLE_OTHER_VIDEO, - Crawler.GOOGLE_CLOUDVERTEXBOT, - - // Hive AI - Crawler.HIVE_IMAGESIFTBOT, - - // Huawei - Crawler.HUAWEI_PETALBOT, - Crawler.HUAWEI_PANGUBOT, - - // Hugging Face - Crawler.HUGGINGFACE_BOT, - - // Kangaroo - Crawler.KANGAROO_BOT, - - // Mendable.ai - Crawler.FIRECRAWL_AGENT, - - // Meta - Crawler.META_FACEBOOKBOT, - Crawler.META_EXTERNALAGENT, - - // OpenAI - Crawler.OPENAI_GPTBOT, - Crawler.OPENAI_SEARCH_BOT, - - // Perplexity - Crawler.PERPLEXITY_BOT, - - // Replicate - Crawler.REPLICATE_BOT, - - // Runpod - Crawler.RUNPOD_BOT, - - // SB Intuitions - Crawler.SB_INTUITIONS_BOT, - - // Semrush - Crawler.SEMRUSH_BOT_CONTENTSHAKE, - - // Timpi - Crawler.TIMPI_BOT, - - // Together AI - Crawler.TOGETHER_BOT, - - // Velen.io - Crawler.HUNTER_VELENPUBLICWEBCRAWLER, - - // Vercel - Crawler.VERCEL_V0BOT, - - // Webz.io - Crawler.WEBZIO_OMGILI, - Crawler.WEBZIO_OMGILI_BOT, - Crawler.WEBZIO_EXTENDED, - - // X - Crawler.XAI_BOT, - - // You.com - Crawler.YOU_BOT, - - // Zhipu AI - Crawler.ZHIPU_CHATGLM_SPIDER - ] - .map((s) => s.toLowerCase()) - .includes(String(toResult(resultOrUA, Crawlers).browser.name).toLowerCase()); - -const isBot = (resultOrUA) => [ - BrowserType.CLI, - BrowserType.CRAWLER, - BrowserType.FETCHER, - BrowserType.LIBRARY - ].includes(toResult(resultOrUA, Bots).browser.type); - -const isChromeFamily = (resultOrUA) => toResult(resultOrUA).engine.is(EngineName.BLINK); +const isChromeFamily = val => !!((typeof val === 'string' ? new UAParser(val).getEngine() : val.engine)?.is(EngineName.BLINK)); const isElectron = () => !!(process?.versions?.hasOwnProperty('electron') || // node.js / electron\//i.test(navigator?.userAgent)); // browser