From bd5cb7186c804778a69ba7047939dc6a74d6004d Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 15:15:13 +0200 Subject: [PATCH] feat: add named exports for tree shaking support with modern bundlers (#566) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: naorpeled <6171622+naorpeled@users.noreply.github.com> Co-authored-by: naorpeled --- index.d.ts | 7 +++++ src/bowser.js | 6 +++++ test/unit/bowser.js | 63 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index e4b7e41..b78ae12 100644 --- a/index.d.ts +++ b/index.d.ts @@ -5,6 +5,13 @@ export = Bowser; export as namespace Bowser; +export function getParser(UA: string, skipParsing?: boolean): Bowser.Parser.Parser; +export function parse(UA: string): Bowser.Parser.ParsedResult; +export const BROWSER_MAP: Record; +export const ENGINE_MAP: Record; +export const OS_MAP: Record; +export const PLATFORMS_MAP: Record; + declare namespace Bowser { /** * Creates a Parser instance diff --git a/src/bowser.js b/src/bowser.js index f79e6e0..311ce89 100644 --- a/src/bowser.js +++ b/src/bowser.js @@ -75,3 +75,9 @@ class Bowser { } export default Bowser; + +export const { getParser } = Bowser; +export const { parse } = Bowser; +export { + BROWSER_MAP, ENGINE_MAP, OS_MAP, PLATFORMS_MAP, +}; diff --git a/test/unit/bowser.js b/test/unit/bowser.js index a27b2c9..f568893 100644 --- a/test/unit/bowser.js +++ b/test/unit/bowser.js @@ -1,5 +1,5 @@ import test from 'ava'; -import Bowser from '../../src/bowser'; +import Bowser, { getParser, parse, BROWSER_MAP, ENGINE_MAP, OS_MAP, PLATFORMS_MAP } from '../../src/bowser'; import Parser from '../../src/parser'; const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.1165'; @@ -16,3 +16,64 @@ test('Bowser`s constructor fails if UA is empty', (t) => { test('Bowser.parse parses UA and returns result', (t) => { t.deepEqual(Bowser.parse(UA), browser.getResult()); }); + +test('Named export getParser works like Bowser.getParser', (t) => { + const namedExportParser = getParser(UA); + t.truthy(namedExportParser instanceof Parser); + t.deepEqual(namedExportParser.getResult(), browser.getResult()); +}); + +test('Named export getParser with skipParsing parameter', (t) => { + const parserWithSkip = getParser(UA, true); + t.truthy(parserWithSkip instanceof Parser); + // With skipParsing=true, the result should be undefined until we explicitly parse + t.deepEqual(parserWithSkip.getResult(), Bowser.getParser(UA, true).getResult()); +}); + +test('Named export getParser throws error for invalid UA', (t) => { + t.throws(() => getParser(undefined), { message: 'UserAgent should be a string' }); + t.throws(() => getParser(123), { message: 'UserAgent should be a string' }); + t.throws(() => getParser(null), { message: 'UserAgent should be a string' }); + t.throws(() => getParser({}), { message: 'UserAgent should be a string' }); +}); + +test('Named export parse works like Bowser.parse', (t) => { + t.deepEqual(parse(UA), Bowser.parse(UA)); +}); + +test('Named export parse produces consistent results', (t) => { + const result1 = parse(UA); + const result2 = parse(UA); + t.deepEqual(result1, result2); + t.deepEqual(result1, Bowser.parse(UA)); +}); + +test('Named exports of constants are available', (t) => { + t.truthy(BROWSER_MAP); + t.truthy(ENGINE_MAP); + t.truthy(OS_MAP); + t.truthy(PLATFORMS_MAP); + t.is(BROWSER_MAP, Bowser.BROWSER_MAP); + t.is(ENGINE_MAP, Bowser.ENGINE_MAP); + t.is(OS_MAP, Bowser.OS_MAP); + t.is(PLATFORMS_MAP, Bowser.PLATFORMS_MAP); +}); + +test('Named exports constants are objects with expected structure', (t) => { + t.is(typeof BROWSER_MAP, 'object'); + t.is(typeof ENGINE_MAP, 'object'); + t.is(typeof OS_MAP, 'object'); + t.is(typeof PLATFORMS_MAP, 'object'); +}); + +test('All named exports work together', (t) => { + // Test that we can use multiple named exports in the same scope + const result = parse(UA); + const parser = getParser(UA); + + t.deepEqual(result, parser.getResult()); + t.truthy(BROWSER_MAP); + t.truthy(ENGINE_MAP); + t.truthy(OS_MAP); + t.truthy(PLATFORMS_MAP); +});