├── .gitignore ├── .npmignore ├── .prettierrc ├── .travis.yml ├── LICENSE ├── README.md ├── examples ├── simple.js ├── switch.js └── use-discriminator.ts ├── package.json ├── src └── index.ts ├── test ├── highLevel.js ├── index.js └── logic.js ├── tsconfig.json ├── tslint.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | index.js 2 | index.d.ts 3 | node_modules 4 | npm-debug.log 5 | .idea 6 | es 7 | yarn-error.log 8 | package-lock.json 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | examples 2 | test 3 | .travis.yml 4 | .prettierrc 5 | tsconfig.json 6 | tslint.json 7 | src 8 | !index.js 9 | !index.d.ts 10 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | singleQuote: true 2 | trailingComma: "all" 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - stable 4 | 5 | notifications: 6 | email: 7 | - damon.oehlman@gmail.com 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Damon Oehlman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # detect-browser 2 | 3 | This is a package that attempts to detect a browser vendor and version (in 4 | a semver compatible format) using a navigator useragent in a browser or 5 | `process.version` in node. 6 | 7 | [![NPM](https://nodei.co/npm/detect-browser.png)](https://nodei.co/npm/detect-browser/) 8 | 9 | [![stable](https://img.shields.io/badge/stability-stable-green.svg)](https://github.com/dominictarr/stability#stable) [![Build Status](https://api.travis-ci.org/DamonOehlman/detect-browser.svg?branch=master)](https://travis-ci.org/DamonOehlman/detect-browser) [![Maintainability](https://api.codeclimate.com/v1/badges/84947fce3f3b06da69d0/maintainability)](https://codeclimate.com/github/DamonOehlman/detect-browser/maintainability) 10 | 11 | ## Installation 12 | 13 | [![CDN](https://img.shields.io/badge/CDN-UNPKG-blue.svg)](https://unpkg.com/browse/detect-browser) 14 | 15 | [![NPM](https://img.shields.io/badge/Package-npm-purple.svg)](https://www.npmjs.com/package/detect-browser) 16 | 17 | ## Release History 18 | 19 | Release history can be found in the [github releases list](https://github.com/DamonOehlman/detect-browser/releases). 20 | 21 | --- 22 | 23 | ## Example Usage 24 | 25 | ```js 26 | const { detect } = require('detect-browser'); 27 | const browser = detect(); 28 | 29 | // handle the case where we don't detect the browser 30 | if (browser) { 31 | console.log(browser.name); 32 | console.log(browser.version); 33 | console.log(browser.os); 34 | } 35 | ``` 36 | 37 | Or you can use a switch statement: 38 | 39 | ```js 40 | const { detect } = require('detect-browser'); 41 | const browser = detect(); 42 | 43 | // handle the case where we don't detect the browser 44 | switch (browser && browser.name) { 45 | case 'chrome': 46 | case 'firefox': 47 | console.log('supported'); 48 | break; 49 | 50 | case 'edge': 51 | console.log('kinda ok'); 52 | break; 53 | 54 | default: 55 | console.log('not supported'); 56 | } 57 | ``` 58 | 59 | Additionally, from `5.x` a `type` discriminator is included in the result 60 | should you want to use this (it's a nice convenience in a TS environment). 61 | 62 | Contrived example: 63 | 64 | ```ts 65 | import { detect } from '../src'; 66 | 67 | const result = detect(); 68 | if (result) { 69 | switch (result.type) { 70 | case 'bot': 71 | // result is an instanceof BotInfo 72 | console.log(`found ${result.name} bot`); 73 | break; 74 | 75 | case 'bot-device': 76 | // result is an instanceof SearchBotDeviceInfo 77 | console.log(`found ${result.name} device bot`); 78 | break; 79 | 80 | case 'browser': 81 | // result is an instanceof BrowserInfo 82 | console.log(`found ${result.name} browser`); 83 | break; 84 | 85 | case 'node': 86 | // result is an instanceof NodeInfo 87 | console.log(`found node version ${result.version}`); 88 | break; 89 | } 90 | } 91 | ``` 92 | 93 | **NOTE:** In addition to the the `detect` function, `browserName` and 94 | `detectOS` are provided as exports if you want to only access certain 95 | information. 96 | 97 | An editable observable workbook is [available here](https://observablehq.com/@rayshan/browser-detection-tester-using-the-detect-browser-package). 98 | 99 | ## Adding additional browser support 100 | 101 | The current list of browsers that can be detected by `detect-browser` is 102 | not exhaustive. If you have a browser that you would like to add support for 103 | then please submit a pull request with the implementation. 104 | 105 | Creating an acceptable implementation requires two things: 106 | 107 | 1. A test demonstrating that the regular expression you have defined identifies 108 | your new browser correctly. Examples of this can be found in the 109 | `test/logic.js` file. 110 | 111 | 2. Write the actual regex to the `index.js` file. In most cases adding 112 | the regex to the list of existing regexes will be suitable (if usage of `detect-browser` 113 | returns `undefined` for instance), but in some cases you might have to add it before 114 | an existing regex. This would be true for a case where you have a browser that 115 | is a specialised variant of an existing browser but is identified as the 116 | non-specialised case. 117 | 118 | When writing the regular expression remember that you would write it containing a 119 | single [capturing group](https://regexone.com/lesson/capturing_groups) which 120 | captures the version number of the browser. 121 | 122 | ## LICENSE 123 | 124 | The MIT License (MIT) 125 | 126 | Copyright (c) 2019 Damon Oehlman 127 | 128 | Permission is hereby granted, free of charge, to any person obtaining a copy 129 | of this software and associated documentation files (the "Software"), to deal 130 | in the Software without restriction, including without limitation the rights 131 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 132 | copies of the Software, and to permit persons to whom the Software is 133 | furnished to do so, subject to the following conditions: 134 | 135 | The above copyright notice and this permission notice shall be included in all 136 | copies or substantial portions of the Software. 137 | 138 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 139 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 140 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 141 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 142 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 143 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 144 | SOFTWARE. 145 | -------------------------------------------------------------------------------- /examples/simple.js: -------------------------------------------------------------------------------- 1 | const { detect } = require('..'); 2 | const browser = detect(); 3 | 4 | // handle the case where we don't detect the browser 5 | if (browser) { 6 | console.log(browser.name); 7 | console.log(browser.version); 8 | console.log(browser.os); 9 | } 10 | -------------------------------------------------------------------------------- /examples/switch.js: -------------------------------------------------------------------------------- 1 | const { detect } = require('..'); 2 | const browser = detect(); 3 | 4 | // handle the case where we don't detect the browser 5 | switch (browser && browser.name) { 6 | case 'chrome': 7 | case 'firefox': 8 | console.log('supported'); 9 | break; 10 | 11 | case 'edge': 12 | console.log('kinda ok'); 13 | break; 14 | 15 | default: 16 | console.log('not supported'); 17 | } 18 | -------------------------------------------------------------------------------- /examples/use-discriminator.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-console */ 2 | import { detect } from '../src'; 3 | 4 | const result = detect(); 5 | if (result) { 6 | switch (result.type) { 7 | case 'bot': 8 | // result is an instanceof BotInfo 9 | console.log(`found ${result.name} bot`); 10 | break; 11 | 12 | case 'bot-device': 13 | // result is an instanceof SearchBotDeviceInfo 14 | console.log(`found ${result.name} device bot`); 15 | break; 16 | 17 | case 'browser': 18 | // result is an instanceof BrowserInfo 19 | console.log(`found ${result.name} browser`); 20 | break; 21 | 22 | case 'node': 23 | // result is an instanceof NodeInfo 24 | console.log(`found node version ${result.version}`); 25 | break; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "detect-browser", 3 | "version": "5.3.0", 4 | "description": "Unpack a browser type and version from the useragent string", 5 | "main": "index.js", 6 | "module": "es/index.js", 7 | "types": "index.d.ts", 8 | "sideEffects": false, 9 | "scripts": { 10 | "pretest": "tsc", 11 | "test": "node test", 12 | "lint": "tslint -c tslint.json src/**", 13 | "compile": "npm-run-all -p compile:commonjs compile:es", 14 | "compile:commonjs": "tsc", 15 | "compile:es": "rimraf es && tsc --outDir es --module es6 --declaration false", 16 | "compile-and-size": "yarn tsc && cat index.js | gzip | wc -c", 17 | "prepare": "npm-run-all compile test lint", 18 | "patch-release": "npm version patch && npm publish && npm run postpublish", 19 | "minor-release": "npm version minor && npm publish && npm run postpublish", 20 | "major-release": "npm version major && npm publish && npm run postpublish", 21 | "postpublish": "git push origin master --follow-tags", 22 | "autoformat": "prettier --write src/** test/**", 23 | "gendocs": "embellish README.md" 24 | }, 25 | "stability": "stable", 26 | "repository": { 27 | "type": "git", 28 | "url": "https://github.com/DamonOehlman/detect-browser.git" 29 | }, 30 | "keywords": [ 31 | "browser", 32 | "detect", 33 | "useragent" 34 | ], 35 | "author": "Damon Oehlman ", 36 | "license": "MIT", 37 | "bugs": { 38 | "url": "https://github.com/DamonOehlman/detect-browser/issues" 39 | }, 40 | "homepage": "https://github.com/DamonOehlman/detect-browser", 41 | "devDependencies": { 42 | "@types/node": "^13.9.1", 43 | "embellish-readme": "^1.7.2", 44 | "npm-run-all": "^4.1.5", 45 | "prettier": "^1.18.2", 46 | "rimraf": "^3.0.2", 47 | "semver": "^7.1.3", 48 | "tape": "^4.11.0", 49 | "tslint": "^6.1.3", 50 | "typescript": "^4.4.3" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export type DetectedInfoType = 2 | | 'browser' 3 | | 'node' 4 | | 'bot-device' 5 | | 'bot' 6 | | 'react-native'; 7 | 8 | interface DetectedInfo< 9 | T extends DetectedInfoType, 10 | N extends string, 11 | O, 12 | V = null 13 | > { 14 | readonly type: T; 15 | readonly name: N; 16 | readonly version: V; 17 | readonly os: O; 18 | } 19 | 20 | export class BrowserInfo 21 | implements DetectedInfo<'browser', Browser, OperatingSystem | null, string> { 22 | public readonly type = 'browser'; 23 | constructor( 24 | public readonly name: Browser, 25 | public readonly version: string, 26 | public readonly os: OperatingSystem | null, 27 | ) {} 28 | } 29 | 30 | export class NodeInfo 31 | implements DetectedInfo<'node', 'node', NodeJS.Platform, string> { 32 | public readonly type = 'node'; 33 | public readonly name: 'node' = 'node'; 34 | public readonly os: NodeJS.Platform = process.platform; 35 | 36 | constructor(public readonly version: string) {} 37 | } 38 | 39 | export class SearchBotDeviceInfo 40 | implements 41 | DetectedInfo<'bot-device', Browser, OperatingSystem | null, string> { 42 | public readonly type = 'bot-device'; 43 | constructor( 44 | public readonly name: Browser, 45 | public readonly version: string, 46 | public readonly os: OperatingSystem | null, 47 | public readonly bot: string, 48 | ) {} 49 | } 50 | 51 | export class BotInfo implements DetectedInfo<'bot', 'bot', null, null> { 52 | public readonly type = 'bot'; 53 | public readonly bot: true = true; // NOTE: deprecated test name instead 54 | public readonly name: 'bot' = 'bot'; 55 | public readonly version: null = null; 56 | public readonly os: null = null; 57 | } 58 | 59 | export class ReactNativeInfo 60 | implements DetectedInfo<'react-native', 'react-native', null, null> { 61 | public readonly type = 'react-native'; 62 | public readonly name: 'react-native' = 'react-native'; 63 | public readonly version: null = null; 64 | public readonly os: null = null; 65 | } 66 | 67 | export type Browser = 68 | | 'aol' 69 | | 'edge' 70 | | 'edge-ios' 71 | | 'yandexbrowser' 72 | | 'kakaotalk' 73 | | 'samsung' 74 | | 'silk' 75 | | 'miui' 76 | | 'beaker' 77 | | 'edge-chromium' 78 | | 'chrome' 79 | | 'chromium-webview' 80 | | 'phantomjs' 81 | | 'crios' 82 | | 'firefox' 83 | | 'fxios' 84 | | 'opera-mini' 85 | | 'opera' 86 | | 'pie' 87 | | 'netfront' 88 | | 'ie' 89 | | 'bb10' 90 | | 'android' 91 | | 'ios' 92 | | 'safari' 93 | | 'facebook' 94 | | 'instagram' 95 | | 'ios-webview' 96 | | 'curl' 97 | | 'searchbot'; 98 | export type OperatingSystem = 99 | | 'iOS' 100 | | 'Android OS' 101 | | 'BlackBerry OS' 102 | | 'Windows Mobile' 103 | | 'Amazon OS' 104 | | 'Windows 3.11' 105 | | 'Windows 95' 106 | | 'Windows 98' 107 | | 'Windows 2000' 108 | | 'Windows XP' 109 | | 'Windows Server 2003' 110 | | 'Windows Vista' 111 | | 'Windows 7' 112 | | 'Windows 8' 113 | | 'Windows 8.1' 114 | | 'Windows 10' 115 | | 'Windows ME' 116 | | 'Windows CE' 117 | | 'Open BSD' 118 | | 'Sun OS' 119 | | 'Linux' 120 | | 'Mac OS' 121 | | 'QNX' 122 | | 'BeOS' 123 | | 'OS/2' 124 | | 'Chrome OS'; 125 | type UserAgentRule = [Browser, RegExp]; 126 | type UserAgentMatch = [Browser, RegExpExecArray] | false; 127 | type OperatingSystemRule = [OperatingSystem, RegExp]; 128 | 129 | // tslint:disable-next-line:max-line-length 130 | const SEARCHBOX_UA_REGEX = /alexa|bot|crawl(er|ing)|facebookexternalhit|feedburner|google web preview|nagios|postrank|pingdom|slurp|spider|yahoo!|yandex/; 131 | const SEARCHBOT_OS_REGEX = /(nuhk|curl|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask\ Jeeves\/Teoma|ia_archiver)/; 132 | const REQUIRED_VERSION_PARTS = 3; 133 | 134 | const userAgentRules: UserAgentRule[] = [ 135 | ['aol', /AOLShield\/([0-9\._]+)/], 136 | ['edge', /Edge\/([0-9\._]+)/], 137 | ['edge-ios', /EdgiOS\/([0-9\._]+)/], 138 | ['yandexbrowser', /YaBrowser\/([0-9\._]+)/], 139 | ['kakaotalk', /KAKAOTALK\s([0-9\.]+)/], 140 | ['samsung', /SamsungBrowser\/([0-9\.]+)/], 141 | ['silk', /\bSilk\/([0-9._-]+)\b/], 142 | ['miui', /MiuiBrowser\/([0-9\.]+)$/], 143 | ['beaker', /BeakerBrowser\/([0-9\.]+)/], 144 | ['edge-chromium', /EdgA?\/([0-9\.]+)/], 145 | [ 146 | 'chromium-webview', 147 | /(?!Chrom.*OPR)wv\).*Chrom(?:e|ium)\/([0-9\.]+)(:?\s|$)/, 148 | ], 149 | ['chrome', /(?!Chrom.*OPR)Chrom(?:e|ium)\/([0-9\.]+)(:?\s|$)/], 150 | ['phantomjs', /PhantomJS\/([0-9\.]+)(:?\s|$)/], 151 | ['crios', /CriOS\/([0-9\.]+)(:?\s|$)/], 152 | ['firefox', /Firefox\/([0-9\.]+)(?:\s|$)/], 153 | ['fxios', /FxiOS\/([0-9\.]+)/], 154 | ['opera-mini', /Opera Mini.*Version\/([0-9\.]+)/], 155 | ['opera', /Opera\/([0-9\.]+)(?:\s|$)/], 156 | ['opera', /OPR\/([0-9\.]+)(:?\s|$)/], 157 | ['pie',/^Microsoft Pocket Internet Explorer\/(\d+\.\d+)$/], 158 | ['pie',/^Mozilla\/\d\.\d+\s\(compatible;\s(?:MSP?IE|MSInternet Explorer) (\d+\.\d+);.*Windows CE.*\)$/], 159 | ['netfront',/^Mozilla\/\d\.\d+.*NetFront\/(\d.\d)/], 160 | ['ie', /Trident\/7\.0.*rv\:([0-9\.]+).*\).*Gecko$/], 161 | ['ie', /MSIE\s([0-9\.]+);.*Trident\/[4-7].0/], 162 | ['ie', /MSIE\s(7\.0)/], 163 | ['bb10', /BB10;\sTouch.*Version\/([0-9\.]+)/], 164 | ['android', /Android\s([0-9\.]+)/], 165 | ['ios', /Version\/([0-9\._]+).*Mobile.*Safari.*/], 166 | ['safari', /Version\/([0-9\._]+).*Safari/], 167 | ['facebook', /FB[AS]V\/([0-9\.]+)/], 168 | ['instagram', /Instagram\s([0-9\.]+)/], 169 | ['ios-webview', /AppleWebKit\/([0-9\.]+).*Mobile/], 170 | ['ios-webview', /AppleWebKit\/([0-9\.]+).*Gecko\)$/], 171 | ['curl', /^curl\/([0-9\.]+)$/], 172 | ['searchbot', SEARCHBOX_UA_REGEX], 173 | ]; 174 | const operatingSystemRules: OperatingSystemRule[] = [ 175 | ['iOS', /iP(hone|od|ad)/], 176 | ['Android OS', /Android/], 177 | ['BlackBerry OS', /BlackBerry|BB10/], 178 | ['Windows Mobile', /IEMobile/], 179 | ['Amazon OS', /Kindle/], 180 | ['Windows 3.11', /Win16/], 181 | ['Windows 95', /(Windows 95)|(Win95)|(Windows_95)/], 182 | ['Windows 98', /(Windows 98)|(Win98)/], 183 | ['Windows 2000', /(Windows NT 5.0)|(Windows 2000)/], 184 | ['Windows XP', /(Windows NT 5.1)|(Windows XP)/], 185 | ['Windows Server 2003', /(Windows NT 5.2)/], 186 | ['Windows Vista', /(Windows NT 6.0)/], 187 | ['Windows 7', /(Windows NT 6.1)/], 188 | ['Windows 8', /(Windows NT 6.2)/], 189 | ['Windows 8.1', /(Windows NT 6.3)/], 190 | ['Windows 10', /(Windows NT 10.0)/], 191 | ['Windows ME', /Windows ME/], 192 | ['Windows CE', /Windows CE|WinCE|Microsoft Pocket Internet Explorer/], 193 | ['Open BSD', /OpenBSD/], 194 | ['Sun OS', /SunOS/], 195 | ['Chrome OS', /CrOS/], 196 | ['Linux', /(Linux)|(X11)/], 197 | ['Mac OS', /(Mac_PowerPC)|(Macintosh)/], 198 | ['QNX', /QNX/], 199 | ['BeOS', /BeOS/], 200 | ['OS/2', /OS\/2/], 201 | ]; 202 | 203 | export function detect( 204 | userAgent?: string, 205 | ): 206 | | BrowserInfo 207 | | SearchBotDeviceInfo 208 | | BotInfo 209 | | NodeInfo 210 | | ReactNativeInfo 211 | | null { 212 | if (!!userAgent) { 213 | return parseUserAgent(userAgent); 214 | } 215 | 216 | if ( 217 | typeof document === 'undefined' && 218 | typeof navigator !== 'undefined' && 219 | navigator.product === 'ReactNative' 220 | ) { 221 | return new ReactNativeInfo(); 222 | } 223 | 224 | if (typeof navigator !== 'undefined') { 225 | return parseUserAgent(navigator.userAgent); 226 | } 227 | 228 | return getNodeVersion(); 229 | } 230 | 231 | function matchUserAgent(ua: string): UserAgentMatch { 232 | // opted for using reduce here rather than Array#first with a regex.test call 233 | // this is primarily because using the reduce we only perform the regex 234 | // execution once rather than once for the test and for the exec again below 235 | // probably something that needs to be benchmarked though 236 | return ( 237 | ua !== '' && 238 | userAgentRules.reduce( 239 | (matched: UserAgentMatch, [browser, regex]) => { 240 | if (matched) { 241 | return matched; 242 | } 243 | 244 | const uaMatch = regex.exec(ua); 245 | return !!uaMatch && [browser, uaMatch]; 246 | }, 247 | false, 248 | ) 249 | ); 250 | } 251 | 252 | export function browserName(ua: string): Browser | null { 253 | const data = matchUserAgent(ua); 254 | return data ? data[0] : null; 255 | } 256 | 257 | export function parseUserAgent( 258 | ua: string, 259 | ): BrowserInfo | SearchBotDeviceInfo | BotInfo | null { 260 | const matchedRule: UserAgentMatch = matchUserAgent(ua); 261 | 262 | if (!matchedRule) { 263 | return null; 264 | } 265 | 266 | const [name, match] = matchedRule; 267 | if (name === 'searchbot') { 268 | return new BotInfo(); 269 | } 270 | // Do not use RegExp for split operation as some browser do not support it (See: http://blog.stevenlevithan.com/archives/cross-browser-split) 271 | let versionParts = match[1] && match[1].split('.').join('_').split('_').slice(0, 3); 272 | if (versionParts) { 273 | if (versionParts.length < REQUIRED_VERSION_PARTS) { 274 | versionParts = [ 275 | ...versionParts, 276 | ...createVersionParts(REQUIRED_VERSION_PARTS - versionParts.length), 277 | ]; 278 | } 279 | } else { 280 | versionParts = []; 281 | } 282 | 283 | const version = versionParts.join('.'); 284 | const os = detectOS(ua); 285 | const searchBotMatch = SEARCHBOT_OS_REGEX.exec(ua); 286 | 287 | if (searchBotMatch && searchBotMatch[1]) { 288 | return new SearchBotDeviceInfo(name, version, os, searchBotMatch[1]); 289 | } 290 | 291 | return new BrowserInfo(name, version, os); 292 | } 293 | 294 | export function detectOS(ua: string): OperatingSystem | null { 295 | for (let ii = 0, count = operatingSystemRules.length; ii < count; ii++) { 296 | const [os, regex] = operatingSystemRules[ii]; 297 | const match = regex.exec(ua); 298 | if (match) { 299 | return os; 300 | } 301 | } 302 | 303 | return null; 304 | } 305 | 306 | export function getNodeVersion(): NodeInfo | null { 307 | const isNode = typeof process !== 'undefined' && process.version; 308 | return isNode ? new NodeInfo(process.version.slice(1)) : null; 309 | } 310 | 311 | function createVersionParts(count: number): string[] { 312 | const output = []; 313 | for (let ii = 0; ii < count; ii++) { 314 | output.push('0'); 315 | } 316 | 317 | return output; 318 | } 319 | -------------------------------------------------------------------------------- /test/highLevel.js: -------------------------------------------------------------------------------- 1 | var semver = require('semver'); 2 | var { detect } = require('../'); 3 | var test = require('tape'); 4 | 5 | test('can run detection', function(t) { 6 | t.ok(detect(), 'detection ran ok'); 7 | t.end(); 8 | }); 9 | 10 | test('name detected', function(t) { 11 | const browser = detect(); 12 | t.ok(browser.name, browser.name); 13 | t.end(); 14 | }); 15 | 16 | test('version detected', function(t) { 17 | const browser = detect(); 18 | t.ok(browser.version, browser.version); 19 | t.end(); 20 | }); 21 | 22 | test('version is semver compatible', function(t) { 23 | const browser = detect(); 24 | t.ok(semver.valid(browser.version)); 25 | t.end(); 26 | }); 27 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | require('./highLevel.js'); 2 | require('./logic.js'); 3 | -------------------------------------------------------------------------------- /test/logic.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var { parseUserAgent } = require('../'); 3 | 4 | function assertAgentString(t, agentString, expectedResult) { 5 | t.deepEqual(parseUserAgent(agentString), expectedResult); 6 | } 7 | 8 | test('detects Chrome', function(t) { 9 | assertAgentString( 10 | t, 11 | 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36', 12 | { type: 'browser', name: 'chrome', version: '50.0.2661', os: 'Linux' }, 13 | ); 14 | 15 | assertAgentString( 16 | t, 17 | 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36', 18 | { type: 'browser', name: 'chrome', version: '41.0.2228', os: 'Windows 7' }, 19 | ); 20 | 21 | assertAgentString( 22 | t, 23 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36', 24 | { type: 'browser', name: 'chrome', version: '72.0.3626', os: 'Windows 10' }, 25 | ); 26 | 27 | t.end(); 28 | }); 29 | 30 | test('detects Chrome for iOS', function(t) { 31 | assertAgentString( 32 | t, 33 | 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3', 34 | { type: 'browser', name: 'crios', version: '19.0.1084', os: 'iOS' }, 35 | ); 36 | 37 | t.end(); 38 | }); 39 | 40 | test('detects Firefox', function(t) { 41 | assertAgentString( 42 | t, 43 | 'Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0', 44 | { type: 'browser', name: 'firefox', version: '46.0.0', os: 'Linux' }, 45 | ); 46 | 47 | assertAgentString( 48 | t, 49 | 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1', 50 | { type: 'browser', name: 'firefox', version: '40.1.0', os: 'Windows 7' }, 51 | ); 52 | 53 | t.end(); 54 | }); 55 | 56 | test('detects Firefox for iOS', function(t) { 57 | assertAgentString( 58 | t, 59 | 'Mozilla/5.0 (iPad; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4', 60 | { type: 'browser', name: 'fxios', version: '1.0.0', os: 'iOS' }, 61 | ); 62 | 63 | assertAgentString( 64 | t, 65 | 'Mozilla/5.0 (iPad; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/3.2 Mobile/12F69 Safari/600.1.4', 66 | { type: 'browser', name: 'fxios', version: '3.2.0', os: 'iOS' }, 67 | ); 68 | 69 | t.end(); 70 | }); 71 | 72 | test('detects Edge', function(t) { 73 | assertAgentString( 74 | t, 75 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246', 76 | { type: 'browser', name: 'edge', version: '12.246.0', os: 'Windows 10' }, 77 | ); 78 | 79 | assertAgentString( 80 | t, 81 | 'Mozilla/5.0 (Windows NT 6.3; Win64, x64; Touch) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0 (Touch; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; HPNTDFJS; H9P; InfoPath', 82 | { type: 'browser', name: 'edge', version: '12.0.0', os: 'Windows 8.1' }, 83 | ); 84 | 85 | t.end(); 86 | }); 87 | 88 | test('detects IE', function(t) { 89 | assertAgentString( 90 | t, 91 | 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko', 92 | { type: 'browser', name: 'ie', version: '11.0.0', os: 'Windows 8.1' }, 93 | ); 94 | 95 | assertAgentString( 96 | t, 97 | 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0; MSN 11.61; MSNbMSNI; MSNmen-us; MSNcOTH) like Gecko', 98 | { type: 'browser', name: 'ie', version: '11.0.0', os: 'Windows 10' }, 99 | ); 100 | 101 | assertAgentString( 102 | t, 103 | 'Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0', 104 | { type: 'browser', name: 'ie', version: '10.6.0', os: 'Windows 7' }, 105 | ); 106 | 107 | assertAgentString( 108 | t, 109 | 'Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 5.2; WOW64; .NET CLR 2.0.50727)', 110 | { 111 | type: 'browser', 112 | name: 'ie', 113 | version: '7.0.0', 114 | os: 'Windows Server 2003', 115 | }, 116 | ); 117 | 118 | t.end(); 119 | }); 120 | 121 | test('detects Opera', function(t) { 122 | assertAgentString( 123 | t, 124 | 'Opera/9.80 (J2ME/MIDP; Opera Mini/5.0 (Windows; U; Windows NT 5.1; en) AppleWebKit/886; U; en) Presto/2.4.15', 125 | { type: 'browser', name: 'opera', version: '9.80.0', os: 'Windows XP' }, 126 | ); 127 | 128 | assertAgentString(t, 'Opera/9.25 (Macintosh; Intel Mac OS X; U; en)', { 129 | type: 'browser', 130 | name: 'opera', 131 | version: '9.25.0', 132 | os: 'Mac OS', 133 | }); 134 | 135 | assertAgentString( 136 | t, 137 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36 OPR/38.0.2220.31', 138 | { type: 'browser', name: 'opera', version: '38.0.2220', os: 'Mac OS' }, 139 | ); 140 | 141 | assertAgentString( 142 | t, 143 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.28 Safari/537.36 OPR/61.0.3282.0 (Edition developer)', 144 | { type: 'browser', name: 'opera', version: '61.0.3282', os: 'Mac OS' }, 145 | ); 146 | 147 | t.end(); 148 | }); 149 | 150 | test('detects BlackBerry 10', function(t) { 151 | assertAgentString( 152 | t, 153 | 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/7.2.0.0 Mobile Safari/537.10+', 154 | { type: 'browser', name: 'bb10', version: '7.2.0', os: 'BlackBerry OS' }, 155 | ); 156 | 157 | t.end(); 158 | }); 159 | 160 | test('detects Android Webkit browser', function(t) { 161 | assertAgentString( 162 | t, 163 | 'Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', 164 | { type: 'browser', name: 'android', version: '4.0.3', os: 'Android OS' }, 165 | ); 166 | 167 | t.end(); 168 | }); 169 | 170 | test('detects mobile Safari', function(t) { 171 | assertAgentString( 172 | t, 173 | 'Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25', 174 | { type: 'browser', name: 'ios', version: '6.0.0', os: 'iOS' }, 175 | ); 176 | 177 | assertAgentString( 178 | t, 179 | 'Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5', 180 | { type: 'browser', name: 'ios', version: '5.0.2', os: 'iOS' }, 181 | ); 182 | 183 | t.end(); 184 | }); 185 | 186 | test('detects Safari', function(t) { 187 | assertAgentString( 188 | t, 189 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A', 190 | { type: 'browser', name: 'safari', version: '7.0.3', os: 'Mac OS' }, 191 | ); 192 | 193 | t.end(); 194 | }); 195 | 196 | test('detects Yandex Browser', function(t) { 197 | assertAgentString( 198 | t, 199 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 YaBrowser/16.10.0.2774 Safari/537.36', 200 | { 201 | type: 'browser', 202 | name: 'yandexbrowser', 203 | version: '16.10.0', 204 | os: 'Mac OS', 205 | }, 206 | ); 207 | 208 | t.end(); 209 | }); 210 | 211 | test('detects Kakaotalk Browser', function(t) { 212 | assertAgentString( 213 | t, 214 | 'Netscape 5.0 (iPhone; CPU iPhone OS 10_3 1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E304 KAKAOTALK 6.2.2', 215 | { type: 'browser', name: 'kakaotalk', version: '6.2.2', os: 'iOS' }, 216 | ); 217 | 218 | assertAgentString( 219 | t, 220 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 1 like Mac OS X) AppleWebKit/ 603.1.30 (KHTML, like Gecko) Mobile/ 14E304 KAKAOTALK 6.2.2', 221 | { type: 'browser', name: 'kakaotalk', version: '6.2.2', os: 'iOS' }, 222 | ); 223 | 224 | t.end(); 225 | }); 226 | 227 | test('detects PhantomJS Browser', function(t) { 228 | assertAgentString( 229 | t, 230 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1', 231 | { type: 'browser', name: 'phantomjs', version: '2.1.1', os: 'Mac OS' }, 232 | ); 233 | 234 | t.end(); 235 | }); 236 | 237 | test('detects AOLShield Browser', function(t) { 238 | assertAgentString( 239 | t, 240 | 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2841.00 Safari/537.36 AOLShield/54.0.2848.0', 241 | { type: 'browser', name: 'aol', version: '54.0.2848', os: 'Windows 10' }, 242 | ); 243 | 244 | t.end(); 245 | }); 246 | 247 | test('detects facebook in-app browser', function(t) { 248 | assertAgentString( 249 | t, 250 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_5 like Mac OS X) AppleWebKit/604.5.6 (KHTML, like Gecko) Mobile/15D60 [FBAN/FBIOS;FBAV/157.0.0.42.96;FBBV/90008621;FBDV/iPhone9,1;FBMD/iPhone;FBSN/iOS;FBSV/11.2.5;FBSS/2;FBCR/Verizon;FBID/phone;FBLC/en_US;FBOP/5;FBRV/0]', 251 | { type: 'browser', name: 'facebook', version: '157.0.0', os: 'iOS' }, 252 | ); 253 | 254 | t.end(); 255 | }); 256 | 257 | test('detects instagram in-app browser', function(t) { 258 | assertAgentString( 259 | t, 260 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_2 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13F69 Instagram 8.4.0 (iPhone7,2; iPhone OS 9_3_2; nb_NO; nb-NO; scale=2.00; 750x1334', 261 | { type: 'browser', name: 'instagram', version: '8.4.0', os: 'iOS' }, 262 | ); 263 | 264 | t.end(); 265 | }); 266 | 267 | test('detects native iOS WebView browser', function(t) { 268 | assertAgentString( 269 | t, 270 | 'User-Agent: Mozilla/5.0 (iPad; U; CPU OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile', 271 | { type: 'browser', name: 'ios-webview', version: '533.17.9', os: 'iOS' }, 272 | ); 273 | 274 | assertAgentString( 275 | t, 276 | 'Mozilla/5.0 (iPad; CPU OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E216', 277 | { type: 'browser', name: 'ios-webview', version: '605.1.15', os: 'iOS' }, 278 | ); 279 | 280 | assertAgentString( 281 | t, 282 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16B92', 283 | { type: 'browser', name: 'ios-webview', version: '605.1.15', os: 'iOS' }, 284 | ); 285 | 286 | assertAgentString( 287 | t, 288 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko)', 289 | { type: 'browser', name: 'ios-webview', version: '605.1.15', os: 'iOS' }, 290 | ); 291 | 292 | t.end(); 293 | }); 294 | 295 | test('detects Samsung Internet browser', function(t) { 296 | assertAgentString( 297 | t, 298 | 'Mozilla/5.0 (Linux; Android 5.0.2; SAMSUNG SM-G925F Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile Safari/537.36', 299 | { type: 'browser', name: 'samsung', version: '4.0.0', os: 'Android OS' }, 300 | ); 301 | 302 | t.end(); 303 | }); 304 | 305 | test('detects crawler: AhrefsBot', function(t) { 306 | assertAgentString( 307 | t, 308 | 'Mozilla/5.0 (compatible; AhrefsBot/5.2; +http://ahrefs.com/robot/)', 309 | { type: 'bot', bot: true, name: 'bot', version: null, os: null }, 310 | ); 311 | 312 | t.end(); 313 | }); 314 | 315 | test('detects crawler: GoogleBot', function(t) { 316 | assertAgentString( 317 | t, 318 | 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Googlebot/2.1; +http://www.google.com/bot.html) Safari/537.36', 319 | { type: 'bot', bot: true, name: 'bot', version: null, os: null }, 320 | ); 321 | 322 | t.end(); 323 | }); 324 | 325 | test('detects crawler: YandexBot', function(t) { 326 | assertAgentString( 327 | t, 328 | 'Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)', 329 | { type: 'bot', bot: true, name: 'bot', version: null, os: null }, 330 | ); 331 | 332 | t.end(); 333 | }); 334 | 335 | test('detects Opera-Mini', function(t) { 336 | assertAgentString( 337 | t, 338 | 'Opera/9.80 (Android; Opera Mini/8.0.1807/36.1609; U; en) Presto/2.12.423 Version/12.16', 339 | { 340 | type: 'browser', 341 | name: 'opera-mini', 342 | version: '12.16.0', 343 | os: 'Android OS', 344 | }, 345 | ); 346 | 347 | assertAgentString( 348 | t, 349 | 'Opera/9.80 (BlackBerry; Opera Mini/6.5.27548/27.2020; U; en) Presto/2.8.119 Version/11.10', 350 | { 351 | type: 'browser', 352 | name: 'opera-mini', 353 | version: '11.10.0', 354 | os: 'BlackBerry OS', 355 | }, 356 | ); 357 | t.end(); 358 | }); 359 | 360 | test('detects Silk', function(t) { 361 | assertAgentString( 362 | t, 363 | 'Mozilla/5.0 (Linux; Android 4.4.3; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.54 like Chrome/44.0.2403.63 Safari/537.36', 364 | { type: 'browser', name: 'silk', version: '44.1.54', os: 'Android OS' }, 365 | ); 366 | 367 | assertAgentString( 368 | t, 369 | 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.54 like Chrome/44.0.2403.63 Safari/537.36', 370 | { type: 'browser', name: 'silk', version: '44.1.54', os: 'Linux' }, 371 | ); 372 | 373 | assertAgentString( 374 | t, 375 | 'Mozilla/5.0 (Linux; U; Android 4.4.3; KFTHWI Build/KTU84M) AppleWebKit/537.36 (KHTML, like Gecko) Silk/44.1.54 like Chrome/44.0.2403.63 Mobile Safari/537.36', 376 | { type: 'browser', name: 'silk', version: '44.1.54', os: 'Android OS' }, 377 | ); 378 | 379 | t.end(); 380 | }); 381 | 382 | test('detects Chrome OS', function(t) { 383 | assertAgentString( 384 | t, 385 | 'Mozilla/5.0 (X11; CrOS x86_64 10895.78.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.120 Safari/537.36', 386 | { type: 'browser', name: 'chrome', version: '69.0.3497', os: 'Chrome OS' }, 387 | ); 388 | 389 | assertAgentString( 390 | t, 391 | 'Mozilla/5.0 (X11; U; CrOS i686 9.10.0; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Gecko/20100101 Firefox/29.0', 392 | { type: 'browser', name: 'firefox', version: '29.0.0', os: 'Chrome OS' }, 393 | ); 394 | t.end(); 395 | }); 396 | 397 | test('detects miui', function(t) { 398 | assertAgentString( 399 | t, 400 | 'Mozilla/5.0 (Linux; U; Android 7.0; en-us; MI 5 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/9.0.3', 401 | { type: 'browser', name: 'miui', version: '9.0.3', os: 'Android OS' }, 402 | ); 403 | t.end(); 404 | }); 405 | 406 | test('detects Beaker Browser', function(t) { 407 | assertAgentString( 408 | t, 409 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) BeakerBrowser/0.8.7 Chrome/69.0.3497.128 Electron/4.1.3 Safari/537.36', 410 | { type: 'browser', name: 'beaker', version: '0.8.7', os: 'Windows 10' }, 411 | ); 412 | t.end(); 413 | }); 414 | 415 | test('detects edge chromium', function(t) { 416 | assertAgentString( 417 | t, 418 | 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.48 Safari/537.36 Edg/74.1.96.24', 419 | { 420 | type: 'browser', 421 | name: 'edge-chromium', 422 | version: '74.1.96', 423 | os: 'Windows 10', 424 | }, 425 | ); 426 | t.end(); 427 | }); 428 | 429 | test('detects edge chromium (android os)', function(t) { 430 | assertAgentString( 431 | t, 432 | 'Mozilla/5.0 (Linux; Android 9; SM-N950F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.116 Mobile Safari/537.36 EdgA/45.08.4.5074', 433 | { 434 | type: 'browser', 435 | name: 'edge-chromium', 436 | version: '45.08.4', 437 | os: 'Android OS', 438 | }, 439 | ); 440 | t.end(); 441 | }); 442 | 443 | test('detects edge iOS', function(t) { 444 | assertAgentString( 445 | t, 446 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_1_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 EdgiOS/44.2.1 Mobile/16D57 Safari/605.1.15', 447 | { type: 'browser', name: 'edge-ios', version: '44.2.1', os: 'iOS' }, 448 | ); 449 | t.end(); 450 | }); 451 | 452 | test('handles no browser', function(t) { 453 | assertAgentString(t, null, null); 454 | 455 | t.end(); 456 | }); 457 | 458 | /* https://developer.chrome.com/multidevice/user-agent */ 459 | test('detects Chromium-based WebView On Android', function(t) { 460 | assertAgentString( 461 | t, 462 | 'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.65 Mobile Safari/537.36', 463 | { 464 | type: 'browser', 465 | name: 'chromium-webview', 466 | version: '43.0.2357', 467 | os: 'Android OS', 468 | }, 469 | ); 470 | t.end(); 471 | }); 472 | 473 | test('detects extended bot info', function(t) { 474 | assertAgentString( 475 | t, 476 | 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)', 477 | { 478 | type: 'bot-device', 479 | name: 'chrome', 480 | version: '41.0.2272', 481 | os: 'Android OS', 482 | bot: 'Googlebot', 483 | }, 484 | ); 485 | 486 | t.end(); 487 | }); 488 | 489 | /** Windows CE Ozone (CE 4.2 P/PC 2003) */ 490 | test('detects PocketPC2003', function(t) { 491 | assertAgentString( 492 | t, 493 | 'Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; 240x320)', 494 | { 495 | type: 'browser', 496 | name: 'pie', 497 | version: '4.01.0', 498 | os: 'Windows CE', 499 | }, 500 | ); 501 | 502 | t.end(); 503 | }); 504 | 505 | /** Windows CE Pegasus (CE 1.0x) PIE 1.1 */ 506 | test('detects PIE 1.1', function(t) { 507 | assertAgentString( 508 | t, 509 | 'Mozilla/1.1 (compatible; MSPIE 1.1; Windows CE)', 510 | { 511 | type: 'browser', 512 | name: 'pie', 513 | version: '1.1.0', 514 | os: 'Windows CE', 515 | }, 516 | ); 517 | 518 | t.end(); 519 | }); 520 | 521 | 522 | /** Windows CE Stinger SmartPhone 2003 */ 523 | test('detects NetFront', function(t) { 524 | assertAgentString( 525 | t, 526 | 'Mozilla/4.0 (PDA; Windows CE;1.0.0) NetFront/3.0', 527 | { 528 | type: 'browser', 529 | name: 'netfront', 530 | version: '3.0.0', 531 | os: 'Windows CE', 532 | }, 533 | ); 534 | 535 | t.end(); 536 | }); 537 | 538 | test('detects extended bot info', function(t) { 539 | assertAgentString( 540 | t, 541 | 'curl/7.64.1', 542 | { 543 | type: 'bot-device', 544 | name: 'curl', 545 | version: '7.64.1', 546 | os: null, 547 | bot: 'curl', 548 | }, 549 | ); 550 | 551 | t.end(); 552 | }); 553 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "lib": ["es5", "dom"], 6 | "declaration": true, 7 | "outDir": "./", 8 | "rootDir": "./src/", 9 | "strict": true, 10 | "types": ["node"] 11 | }, 12 | "include": [ 13 | "./src/**/*.ts" 14 | ], 15 | "exclude": ["node_modules"] 16 | } 17 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rules": { 4 | "quotemark": [true, "single"], 5 | "interface-name": [true, "never-prefix"], 6 | "max-classes-per-file": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.8.3" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" 8 | integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== 9 | dependencies: 10 | "@babel/highlight" "^7.8.3" 11 | 12 | "@babel/highlight@^7.8.3": 13 | version "7.8.3" 14 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" 15 | integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== 16 | dependencies: 17 | chalk "^2.0.0" 18 | esutils "^2.0.2" 19 | js-tokens "^4.0.0" 20 | 21 | "@types/node@^13.9.1": 22 | version "13.9.1" 23 | resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.1.tgz#96f606f8cd67fb018847d9b61e93997dabdefc72" 24 | integrity sha512-E6M6N0blf/jiZx8Q3nb0vNaswQeEyn0XlupO+xN6DtJ6r6IT4nXrTry7zhIfYvFCl3/8Cu6WIysmUBKiqV0bqQ== 25 | 26 | ansi-styles@^3.2.1: 27 | version "3.2.1" 28 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 29 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 30 | dependencies: 31 | color-convert "^1.9.0" 32 | 33 | argparse@^1.0.7: 34 | version "1.0.10" 35 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 36 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 37 | dependencies: 38 | sprintf-js "~1.0.2" 39 | 40 | balanced-match@^1.0.0: 41 | version "1.0.0" 42 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 43 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 44 | 45 | bent@^7.3.10: 46 | version "7.3.10" 47 | resolved "https://registry.yarnpkg.com/bent/-/bent-7.3.10.tgz#3c58a218b51c1efc9e0381a4f230b2f437184cb9" 48 | integrity sha512-X2P2nGRWejGn6IjJfL4usOuAVMng1DdyuRhXLGOcUvEblBcLZenrSjlkgS8ob1s3tbq3mo1FDxKhCRNvcf0y0Q== 49 | dependencies: 50 | bytesish "^0.4.1" 51 | caseless "~0.12.0" 52 | is-stream "^2.0.0" 53 | 54 | brace-expansion@^1.1.7: 55 | version "1.1.11" 56 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 57 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 58 | dependencies: 59 | balanced-match "^1.0.0" 60 | concat-map "0.0.1" 61 | 62 | builtin-modules@^1.1.1: 63 | version "1.1.1" 64 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" 65 | integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= 66 | 67 | bytesish@^0.4.1: 68 | version "0.4.3" 69 | resolved "https://registry.yarnpkg.com/bytesish/-/bytesish-0.4.3.tgz#886b4c5d0eb5d46678cbfaa2c5fc7d706527b00f" 70 | integrity sha512-OuwahLpcvvYfFnxZL0E/Gx6D7U2A72JM8cXL+5uiiZP/x84B/arG5kL8QfRLCLKb/Ttp1Jk2bPDLeltP96dtbw== 71 | 72 | caseless@~0.12.0: 73 | version "0.12.0" 74 | resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 75 | integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= 76 | 77 | chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1: 78 | version "2.4.2" 79 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 80 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 81 | dependencies: 82 | ansi-styles "^3.2.1" 83 | escape-string-regexp "^1.0.5" 84 | supports-color "^5.3.0" 85 | 86 | color-convert@^1.9.0: 87 | version "1.9.3" 88 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 89 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 90 | dependencies: 91 | color-name "1.1.3" 92 | 93 | color-name@1.1.3: 94 | version "1.1.3" 95 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 96 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 97 | 98 | commander@^2.12.1: 99 | version "2.20.3" 100 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 101 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 102 | 103 | concat-map@0.0.1: 104 | version "0.0.1" 105 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 106 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 107 | 108 | cross-spawn@^6.0.5: 109 | version "6.0.5" 110 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 111 | integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== 112 | dependencies: 113 | nice-try "^1.0.4" 114 | path-key "^2.0.1" 115 | semver "^5.5.0" 116 | shebang-command "^1.2.0" 117 | which "^1.2.9" 118 | 119 | debug@^4.1.1: 120 | version "4.1.1" 121 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" 122 | integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== 123 | dependencies: 124 | ms "^2.1.1" 125 | 126 | deep-equal@~1.1.1: 127 | version "1.1.1" 128 | resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" 129 | integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== 130 | dependencies: 131 | is-arguments "^1.0.4" 132 | is-date-object "^1.0.1" 133 | is-regex "^1.0.4" 134 | object-is "^1.0.1" 135 | object-keys "^1.1.1" 136 | regexp.prototype.flags "^1.2.0" 137 | 138 | define-properties@^1.1.2, define-properties@^1.1.3: 139 | version "1.1.3" 140 | resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" 141 | integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== 142 | dependencies: 143 | object-keys "^1.0.12" 144 | 145 | defined@~1.0.0: 146 | version "1.0.0" 147 | resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" 148 | integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= 149 | 150 | diff@^4.0.1: 151 | version "4.0.2" 152 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" 153 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 154 | 155 | dotignore@~0.1.2: 156 | version "0.1.2" 157 | resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" 158 | integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== 159 | dependencies: 160 | minimatch "^3.0.4" 161 | 162 | embellish-readme@^1.7.2: 163 | version "1.7.2" 164 | resolved "https://registry.yarnpkg.com/embellish-readme/-/embellish-readme-1.7.2.tgz#eb7aeb1a9334f5addd8be16d81feb563e9e92d93" 165 | integrity sha512-Ps7iC4EBDA4s1otB0Ypovft+6gmaN4t9DQrZPSFLyPzNTX5dNG2f25me6d7pOEzB2D6i2rn5Muj3uGkhgMIuiA== 166 | dependencies: 167 | bent "^7.3.10" 168 | debug "^4.1.1" 169 | fp-ts "^2.8.2" 170 | io-ts "^2.2.10" 171 | marked-ast "^0.3.0" 172 | marked-ast-markdown "^2.1.0" 173 | mustache "^4.0.1" 174 | out "^1.1.0" 175 | 176 | entities@^2.0.2: 177 | version "2.0.3" 178 | resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" 179 | integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== 180 | 181 | error-ex@^1.3.1: 182 | version "1.3.2" 183 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 184 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 185 | dependencies: 186 | is-arrayish "^0.2.1" 187 | 188 | es-abstract@^1.17.0-next.1: 189 | version "1.17.4" 190 | resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184" 191 | integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ== 192 | dependencies: 193 | es-to-primitive "^1.2.1" 194 | function-bind "^1.1.1" 195 | has "^1.0.3" 196 | has-symbols "^1.0.1" 197 | is-callable "^1.1.5" 198 | is-regex "^1.0.5" 199 | object-inspect "^1.7.0" 200 | object-keys "^1.1.1" 201 | object.assign "^4.1.0" 202 | string.prototype.trimleft "^2.1.1" 203 | string.prototype.trimright "^2.1.1" 204 | 205 | es-to-primitive@^1.2.1: 206 | version "1.2.1" 207 | resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" 208 | integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== 209 | dependencies: 210 | is-callable "^1.1.4" 211 | is-date-object "^1.0.1" 212 | is-symbol "^1.0.2" 213 | 214 | escape-string-regexp@^1.0.5: 215 | version "1.0.5" 216 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 217 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 218 | 219 | esprima@^4.0.0: 220 | version "4.0.1" 221 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 222 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 223 | 224 | esutils@^2.0.2: 225 | version "2.0.3" 226 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 227 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 228 | 229 | for-each@~0.3.3: 230 | version "0.3.3" 231 | resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" 232 | integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== 233 | dependencies: 234 | is-callable "^1.1.3" 235 | 236 | fp-ts@^2.8.2: 237 | version "2.8.2" 238 | resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.8.2.tgz#7948dea1ceef32e487d7f7f47bd2d3c4fcccfc0d" 239 | integrity sha512-YKLBW75Rp+L9DuY1jr7QO6mZLTmJjy7tOqSAMcB2q2kBomqLjBMyV7dotpcnZmUYY6khMsfgYWtPbUDOFcNmkA== 240 | 241 | fs.realpath@^1.0.0: 242 | version "1.0.0" 243 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 244 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 245 | 246 | function-bind@^1.1.1, function-bind@~1.1.1: 247 | version "1.1.1" 248 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 249 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 250 | 251 | glob@^7.1.1, glob@^7.1.3, glob@~7.1.6: 252 | version "7.1.6" 253 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 254 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 255 | dependencies: 256 | fs.realpath "^1.0.0" 257 | inflight "^1.0.4" 258 | inherits "2" 259 | minimatch "^3.0.4" 260 | once "^1.3.0" 261 | path-is-absolute "^1.0.0" 262 | 263 | graceful-fs@^4.1.2: 264 | version "4.2.3" 265 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" 266 | integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== 267 | 268 | has-flag@^3.0.0: 269 | version "3.0.0" 270 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 271 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 272 | 273 | has-symbols@^1.0.0, has-symbols@^1.0.1: 274 | version "1.0.1" 275 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" 276 | integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== 277 | 278 | has@^1.0.3, has@~1.0.3: 279 | version "1.0.3" 280 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 281 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 282 | dependencies: 283 | function-bind "^1.1.1" 284 | 285 | hosted-git-info@^2.1.4: 286 | version "2.8.8" 287 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" 288 | integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== 289 | 290 | inflight@^1.0.4: 291 | version "1.0.6" 292 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 293 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 294 | dependencies: 295 | once "^1.3.0" 296 | wrappy "1" 297 | 298 | inherits@2, inherits@~2.0.4: 299 | version "2.0.4" 300 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 301 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 302 | 303 | io-ts@^2.2.10: 304 | version "2.2.10" 305 | resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.10.tgz#447d02df51717464a90712b146ec8dbc21b4a74b" 306 | integrity sha512-WHx5jJe7hPpc6JoSIVbD+Xn6tYqe3cRvNpX24d8Wi15/kxhRWa8apo0Gzag6Xg99sCNY9OHKylw/Vhv0JAbNPQ== 307 | 308 | is-arguments@^1.0.4: 309 | version "1.0.4" 310 | resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" 311 | integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== 312 | 313 | is-arrayish@^0.2.1: 314 | version "0.2.1" 315 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 316 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 317 | 318 | is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.1.5: 319 | version "1.1.5" 320 | resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" 321 | integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== 322 | 323 | is-date-object@^1.0.1: 324 | version "1.0.2" 325 | resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" 326 | integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== 327 | 328 | is-regex@^1.0.4, is-regex@^1.0.5, is-regex@~1.0.5: 329 | version "1.0.5" 330 | resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" 331 | integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== 332 | dependencies: 333 | has "^1.0.3" 334 | 335 | is-stream@^2.0.0: 336 | version "2.0.0" 337 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" 338 | integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== 339 | 340 | is-symbol@^1.0.2: 341 | version "1.0.3" 342 | resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" 343 | integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== 344 | dependencies: 345 | has-symbols "^1.0.1" 346 | 347 | isexe@^2.0.0: 348 | version "2.0.0" 349 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 350 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 351 | 352 | js-tokens@^4.0.0: 353 | version "4.0.0" 354 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 355 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 356 | 357 | js-yaml@^3.13.1: 358 | version "3.13.1" 359 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" 360 | integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== 361 | dependencies: 362 | argparse "^1.0.7" 363 | esprima "^4.0.0" 364 | 365 | json-parse-better-errors@^1.0.1: 366 | version "1.0.2" 367 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" 368 | integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== 369 | 370 | load-json-file@^4.0.0: 371 | version "4.0.0" 372 | resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" 373 | integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= 374 | dependencies: 375 | graceful-fs "^4.1.2" 376 | parse-json "^4.0.0" 377 | pify "^3.0.0" 378 | strip-bom "^3.0.0" 379 | 380 | marked-ast-markdown@^2.1.0: 381 | version "2.1.0" 382 | resolved "https://registry.yarnpkg.com/marked-ast-markdown/-/marked-ast-markdown-2.1.0.tgz#1756e237e528c59a10bc04992b7d64bc445f9478" 383 | integrity sha512-vGC/NGGlvyu4I1Uox41a/ScpPbyYL74UWd7GsWjB9pmpmK1iMKqt0d5KdW+wShplefoDZvhm9kRwPlEYE85YGA== 384 | dependencies: 385 | entities "^2.0.2" 386 | whisk "^1.0.0" 387 | 388 | marked-ast@^0.3.0: 389 | version "0.3.0" 390 | resolved "https://registry.yarnpkg.com/marked-ast/-/marked-ast-0.3.0.tgz#dc119d9109fd0be98e915d1e643b9ea24606daec" 391 | integrity sha1-3BGdkQn9C+mOkV0eZDueokYG2uw= 392 | 393 | memorystream@^0.3.1: 394 | version "0.3.1" 395 | resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" 396 | integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= 397 | 398 | minimatch@^3.0.4: 399 | version "3.0.4" 400 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 401 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 402 | dependencies: 403 | brace-expansion "^1.1.7" 404 | 405 | minimist@^1.2.5, minimist@~1.2.0: 406 | version "1.2.5" 407 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 408 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 409 | 410 | mkdirp@^0.5.3: 411 | version "0.5.5" 412 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" 413 | integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== 414 | dependencies: 415 | minimist "^1.2.5" 416 | 417 | ms@^2.1.1: 418 | version "2.1.2" 419 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 420 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 421 | 422 | mustache@^4.0.1: 423 | version "4.0.1" 424 | resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.0.1.tgz#d99beb031701ad433338e7ea65e0489416c854a2" 425 | integrity sha512-yL5VE97+OXn4+Er3THSmTdCFCtx5hHWzrolvH+JObZnUYwuaG7XV+Ch4fR2cIrcYI0tFHxS7iyFYl14bW8y2sA== 426 | 427 | nice-try@^1.0.4: 428 | version "1.0.5" 429 | resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" 430 | integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== 431 | 432 | normalize-package-data@^2.3.2: 433 | version "2.5.0" 434 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" 435 | integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== 436 | dependencies: 437 | hosted-git-info "^2.1.4" 438 | resolve "^1.10.0" 439 | semver "2 || 3 || 4 || 5" 440 | validate-npm-package-license "^3.0.1" 441 | 442 | npm-run-all@^4.1.5: 443 | version "4.1.5" 444 | resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" 445 | integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== 446 | dependencies: 447 | ansi-styles "^3.2.1" 448 | chalk "^2.4.1" 449 | cross-spawn "^6.0.5" 450 | memorystream "^0.3.1" 451 | minimatch "^3.0.4" 452 | pidtree "^0.3.0" 453 | read-pkg "^3.0.0" 454 | shell-quote "^1.6.1" 455 | string.prototype.padend "^3.0.0" 456 | 457 | object-inspect@^1.7.0, object-inspect@~1.7.0: 458 | version "1.7.0" 459 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" 460 | integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== 461 | 462 | object-is@^1.0.1: 463 | version "1.0.2" 464 | resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4" 465 | integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ== 466 | 467 | object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: 468 | version "1.1.1" 469 | resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" 470 | integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== 471 | 472 | object.assign@^4.1.0: 473 | version "4.1.0" 474 | resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" 475 | integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== 476 | dependencies: 477 | define-properties "^1.1.2" 478 | function-bind "^1.1.1" 479 | has-symbols "^1.0.0" 480 | object-keys "^1.0.11" 481 | 482 | once@^1.3.0: 483 | version "1.4.0" 484 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 485 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 486 | dependencies: 487 | wrappy "1" 488 | 489 | out@^1.1.0: 490 | version "1.1.0" 491 | resolved "https://registry.yarnpkg.com/out/-/out-1.1.0.tgz#d607bd5315e3a1733ecddc29b475ddf0c98c672b" 492 | integrity sha512-TfynqaVK+Z42/Cn5zwmdQsCLSs+WGmH+QhPHXhpuYhyiRGlUw/8FKd1LKPAL6B4f1sjIl+zLDegOjDpv6FOfRQ== 493 | 494 | parse-json@^4.0.0: 495 | version "4.0.0" 496 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" 497 | integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= 498 | dependencies: 499 | error-ex "^1.3.1" 500 | json-parse-better-errors "^1.0.1" 501 | 502 | path-is-absolute@^1.0.0: 503 | version "1.0.1" 504 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 505 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 506 | 507 | path-key@^2.0.1: 508 | version "2.0.1" 509 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 510 | integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= 511 | 512 | path-parse@^1.0.6: 513 | version "1.0.6" 514 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 515 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== 516 | 517 | path-type@^3.0.0: 518 | version "3.0.0" 519 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" 520 | integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== 521 | dependencies: 522 | pify "^3.0.0" 523 | 524 | pidtree@^0.3.0: 525 | version "0.3.0" 526 | resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b" 527 | integrity sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg== 528 | 529 | pify@^3.0.0: 530 | version "3.0.0" 531 | resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" 532 | integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= 533 | 534 | prettier@^1.18.2: 535 | version "1.19.1" 536 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" 537 | integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== 538 | 539 | read-pkg@^3.0.0: 540 | version "3.0.0" 541 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" 542 | integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= 543 | dependencies: 544 | load-json-file "^4.0.0" 545 | normalize-package-data "^2.3.2" 546 | path-type "^3.0.0" 547 | 548 | regexp.prototype.flags@^1.2.0: 549 | version "1.3.0" 550 | resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" 551 | integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== 552 | dependencies: 553 | define-properties "^1.1.3" 554 | es-abstract "^1.17.0-next.1" 555 | 556 | resolve@^1.10.0, resolve@^1.3.2, resolve@~1.15.1: 557 | version "1.15.1" 558 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" 559 | integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== 560 | dependencies: 561 | path-parse "^1.0.6" 562 | 563 | resumer@~0.0.0: 564 | version "0.0.0" 565 | resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" 566 | integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= 567 | dependencies: 568 | through "~2.3.4" 569 | 570 | rimraf@^3.0.2: 571 | version "3.0.2" 572 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 573 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 574 | dependencies: 575 | glob "^7.1.3" 576 | 577 | "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0: 578 | version "5.7.1" 579 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 580 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 581 | 582 | semver@^7.1.3: 583 | version "7.1.3" 584 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.3.tgz#e4345ce73071c53f336445cfc19efb1c311df2a6" 585 | integrity sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA== 586 | 587 | shebang-command@^1.2.0: 588 | version "1.2.0" 589 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 590 | integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= 591 | dependencies: 592 | shebang-regex "^1.0.0" 593 | 594 | shebang-regex@^1.0.0: 595 | version "1.0.0" 596 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 597 | integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= 598 | 599 | shell-quote@^1.6.1: 600 | version "1.7.2" 601 | resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" 602 | integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== 603 | 604 | spdx-correct@^3.0.0: 605 | version "3.1.0" 606 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" 607 | integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== 608 | dependencies: 609 | spdx-expression-parse "^3.0.0" 610 | spdx-license-ids "^3.0.0" 611 | 612 | spdx-exceptions@^2.1.0: 613 | version "2.2.0" 614 | resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" 615 | integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== 616 | 617 | spdx-expression-parse@^3.0.0: 618 | version "3.0.0" 619 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" 620 | integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== 621 | dependencies: 622 | spdx-exceptions "^2.1.0" 623 | spdx-license-ids "^3.0.0" 624 | 625 | spdx-license-ids@^3.0.0: 626 | version "3.0.5" 627 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" 628 | integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== 629 | 630 | sprintf-js@~1.0.2: 631 | version "1.0.3" 632 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 633 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 634 | 635 | string.prototype.padend@^3.0.0: 636 | version "3.1.0" 637 | resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz#dc08f57a8010dc5c153550318f67e13adbb72ac3" 638 | integrity sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA== 639 | dependencies: 640 | define-properties "^1.1.3" 641 | es-abstract "^1.17.0-next.1" 642 | 643 | string.prototype.trim@~1.2.1: 644 | version "1.2.1" 645 | resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz#141233dff32c82bfad80684d7e5f0869ee0fb782" 646 | integrity sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw== 647 | dependencies: 648 | define-properties "^1.1.3" 649 | es-abstract "^1.17.0-next.1" 650 | function-bind "^1.1.1" 651 | 652 | string.prototype.trimleft@^2.1.1: 653 | version "2.1.1" 654 | resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" 655 | integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== 656 | dependencies: 657 | define-properties "^1.1.3" 658 | function-bind "^1.1.1" 659 | 660 | string.prototype.trimright@^2.1.1: 661 | version "2.1.1" 662 | resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" 663 | integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== 664 | dependencies: 665 | define-properties "^1.1.3" 666 | function-bind "^1.1.1" 667 | 668 | strip-bom@^3.0.0: 669 | version "3.0.0" 670 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" 671 | integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= 672 | 673 | supports-color@^5.3.0: 674 | version "5.5.0" 675 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 676 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 677 | dependencies: 678 | has-flag "^3.0.0" 679 | 680 | tape@^4.11.0: 681 | version "4.13.2" 682 | resolved "https://registry.yarnpkg.com/tape/-/tape-4.13.2.tgz#eb419b9d9bc004025b1a81a5b63093e07f425629" 683 | integrity sha512-waWwC/OqYVE9TS6r1IynlP2sEdk4Lfo6jazlgkuNkPTHIbuG2BTABIaKdlQWwPeB6Oo4ksZ1j33Yt0NTOAlYMQ== 684 | dependencies: 685 | deep-equal "~1.1.1" 686 | defined "~1.0.0" 687 | dotignore "~0.1.2" 688 | for-each "~0.3.3" 689 | function-bind "~1.1.1" 690 | glob "~7.1.6" 691 | has "~1.0.3" 692 | inherits "~2.0.4" 693 | is-regex "~1.0.5" 694 | minimist "~1.2.0" 695 | object-inspect "~1.7.0" 696 | resolve "~1.15.1" 697 | resumer "~0.0.0" 698 | string.prototype.trim "~1.2.1" 699 | through "~2.3.8" 700 | 701 | through@~2.3.4, through@~2.3.8: 702 | version "2.3.8" 703 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 704 | integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= 705 | 706 | tslib@^1.13.0: 707 | version "1.13.0" 708 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" 709 | integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== 710 | 711 | tslib@^1.8.1: 712 | version "1.11.1" 713 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" 714 | integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== 715 | 716 | tslint@^6.1.3: 717 | version "6.1.3" 718 | resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904" 719 | integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg== 720 | dependencies: 721 | "@babel/code-frame" "^7.0.0" 722 | builtin-modules "^1.1.1" 723 | chalk "^2.3.0" 724 | commander "^2.12.1" 725 | diff "^4.0.1" 726 | glob "^7.1.1" 727 | js-yaml "^3.13.1" 728 | minimatch "^3.0.4" 729 | mkdirp "^0.5.3" 730 | resolve "^1.3.2" 731 | semver "^5.3.0" 732 | tslib "^1.13.0" 733 | tsutils "^2.29.0" 734 | 735 | tsutils@^2.29.0: 736 | version "2.29.0" 737 | resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" 738 | integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== 739 | dependencies: 740 | tslib "^1.8.1" 741 | 742 | typescript@^4.4.3: 743 | version "4.4.3" 744 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324" 745 | integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA== 746 | 747 | validate-npm-package-license@^3.0.1: 748 | version "3.0.4" 749 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" 750 | integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== 751 | dependencies: 752 | spdx-correct "^3.0.0" 753 | spdx-expression-parse "^3.0.0" 754 | 755 | which@^1.2.9: 756 | version "1.3.1" 757 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 758 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 759 | dependencies: 760 | isexe "^2.0.0" 761 | 762 | whisk@^1.0.0: 763 | version "1.4.0" 764 | resolved "https://registry.yarnpkg.com/whisk/-/whisk-1.4.0.tgz#c3fe50b0f585ba73d5915da477c6735c135e8811" 765 | integrity sha512-uh4+hibHa+HxUTUwpP9iiAgyniVB4UBbI6QK2feiv1U9t6PSS32hl/xeAmf0RZhHKXVn3nnNQiju1RzBYVclCg== 766 | 767 | wrappy@1: 768 | version "1.0.2" 769 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 770 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 771 | --------------------------------------------------------------------------------