From 5a0d9cc3d09cc6ab4de3d52e6b798b898b65600e Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Mon, 2 Oct 2023 14:35:29 +0700 Subject: [PATCH] Fix #655 - Provide in-package type definitions --- package.json | 3 ++ script/test-all.sh | 7 ++- src/main/ua-parser.d.ts | 104 ++++++++++++++++++++++++++++++++++++++++ test/dts-test.ts | 42 ++++++++++++++++ 4 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 src/main/ua-parser.d.ts create mode 100644 test/dts-test.ts diff --git a/package.json b/package.json index 444f870..a62cda7 100644 --- a/package.json +++ b/package.json @@ -167,6 +167,7 @@ "Ziding Zhang " ], "type": "commonjs", + "types": "src/main/ua-parser.d.ts", "main": "src/main/ua-parser.js", "module": "src/main/ua-parser.mjs", "browser": "dist/ua-parser.pack.js", @@ -193,6 +194,7 @@ "build+test": "npm run build && npm run test", "fuzz": "jazzer ./test/jazzer-fuzz-test.js --sync", "test": "./script/test-all.sh", + "test:dts": "tsd --typings src/main/ua-parser.d.ts --files test/dts-test.ts", "test:eslint": "eslint src && eslint script", "test:jshint": "jshint src/main", "test:lockfile-lint": "npx lockfile-lint -p package-lock.json", @@ -208,6 +210,7 @@ "mocha": "~8.2.0", "requirejs": "2.3.2", "safe-regex": "^2.1.1", + "tsd": "^0.29.0", "uglify-js": "~3.12.0" }, "repository": { diff --git a/script/test-all.sh b/script/test-all.sh index 37cbd19..ac76616 100755 --- a/script/test-all.sh +++ b/script/test-all.sh @@ -24,4 +24,9 @@ npm run test:playwright || exit 1 echo ' - lint lockfile ' -npm run test:lockfile-lint || exit 1 \ No newline at end of file +npm run test:lockfile-lint || exit 1 + +echo ' +- lint d.ts files +' +npm run test:dts || exit 1 \ No newline at end of file diff --git a/src/main/ua-parser.d.ts b/src/main/ua-parser.d.ts new file mode 100644 index 0000000..8bd52c5 --- /dev/null +++ b/src/main/ua-parser.d.ts @@ -0,0 +1,104 @@ +// Type definitions for UAParser.js v2.0.0-beta +// Project: https://github.com/faisalman/ua-parser-js +// Definitions by: Faisal Salman + +declare namespace UAParser { + + interface IData { + is(val: string): boolean; + toString(): string; + withClientHints(): PromiseLike | T; + withFeatureCheck(): T; + } + + interface IBrowser extends IData { + name?: string; + version?: string; + major?: string; + } + + interface ICPU extends IData { + architecture?: 'ia32' | 'ia64' | 'amd64' | 'arm' | 'arm64' | 'armhf' | 'avr' | 'irix' | 'irix64' | 'mips' | 'mips64' | '68k' | 'ppc' | 'sparc' | 'sparc64'; + } + + interface IDevice extends IData { + type?: 'mobile' | 'tablet' | 'console' | 'smarttv' | 'wearable'; + vendor?: string; + model?: string; + } + + interface IEngine extends IData { + name?: 'Amaya' | 'Blink' | 'EdgeHTML' | 'Flow' | 'Gecko' | 'Goanna' | 'iCab' | 'KHTML' | 'LibWeb' | 'Links' | 'Lynx' | 'NetFront' | 'NetSurf' | 'Presto' | 'Tasman' | 'Trident' | 'w3m' | 'WebKit'; + version?: string; + } + + interface IOS extends IData { + name?: string; + version?: string; + } + + interface IResult extends IData { + ua: string; + browser: IBrowser; + cpu: ICPU; + device: IDevice; + engine: IEngine; + os: IOS; + } + + type RegexMap = ((RegExp | string | (string | RegExp | Function)[])[])[]; + + export function UAParser(uastring?: string, extensions?: Record, headers?: Record): IResult; + export function UAParser(uastring?: string, headers?: Record): IResult; + export function UAParser(extensions?: Record, headers?: Record): IResult; + export function UAParser(headers?: Record): IResult; + + export class UAParser { + + static readonly BROWSER: { + NAME: 'name'; + VERSION: 'version'; + MAJOR: 'major'; + }; + static readonly CPU: { + ARCHITECTURE: 'architecture'; + }; + static readonly DEVICE: { + TYPE: 'type'; + VENDOR: 'vendor'; + MODEL: 'model'; + CONSOLE: 'console'; + MOBILE: 'mobile'; + SMARTTV: 'smarttv'; + TABLET: 'tablet'; + WEARABLE: 'wearable'; + EMBEDDED: 'embedded'; + }; + static readonly ENGINE: { + NAME: 'name'; + VERSION: 'version'; + }; + static readonly OS: { + NAME: 'name'; + VERSION: 'version'; + }; + static readonly VERSION: string; + + constructor(uastring?: string, extensions?: Record, headers?: Record); + constructor(uastring?: string, headers?: Record); + constructor(extensions?: Record, headers?: Record); + constructor(headers?: Record); + + getUA(): string; + getBrowser(): IBrowser; + getCPU(): ICPU; + getDevice(): IDevice; + getEngine(): IEngine; + getOS(): IOS; + getResult(): IResult; + setUA(uastring: string): UAParser; + } +} + +export as namespace UAParser; +export = UAParser; \ No newline at end of file diff --git a/test/dts-test.ts b/test/dts-test.ts new file mode 100644 index 0000000..c060e46 --- /dev/null +++ b/test/dts-test.ts @@ -0,0 +1,42 @@ +import { expectType } from 'tsd'; +import { UAParser, IResult, IBrowser, ICPU, IEngine, IDevice, IOS } from "../src/main/ua-parser"; + +const uastring = 'Mozilla/5.0 (X11; MyCustomOS; Linux i686; rv:19.0) Gecko/20100101 Firefox/19.0'; +const extensions = { + os : [ + [/(mycustomos)/], [UAParser.OS.NAME, [UAParser.OS.VERSION, '10']] + ] +}; +const headers = { + 'sec-ch-ua-mobile' : '?1' +}; + +expectType(UAParser()); +expectType(UAParser(uastring)); +expectType(UAParser(uastring, extensions)); +expectType(UAParser(uastring, headers)); +expectType(UAParser(extensions, headers)); +expectType(UAParser(extensions)); +expectType(UAParser(headers)); +expectType(new UAParser()); + +const parser = new UAParser(uastring); +const browser = parser.getBrowser(); + +expectType(browser); +expectType(browser.name); +expectType(browser.version); +expectType(browser.major); +expectType(browser.is('')); +expectType(browser.toString()); +expectType>(browser.withClientHints()); +expectType((browser.withClientHints()).withFeatureCheck()); +expectType((browser.withClientHints()).withFeatureCheck().is('')); + +expectType(parser.getCPU()); +expectType(parser.getDevice()); +expectType(parser.getEngine()); +expectType(parser.getOS()); +expectType(parser.getResult()); +expectType(parser.getUA()); +expectType(parser.setUA(uastring)); \ No newline at end of file