basant307/AI_Governance_Project
048
1var feature = require('caniuse-lite/dist/unpacker/feature').default2var region = require('caniuse-lite/dist/unpacker/region').default3var fs = require('fs')4var path = require('path')5 6var BrowserslistError = require('./error')7 8var IS_SECTION = /^\s*\[(.+)]\s*$/9var CONFIG_PATTERN = /^browserslist-config-/10var SCOPED_CONFIG__PATTERN = /@[^/]+(?:\/[^/]+)?\/browserslist-config(?:-|$|\/)/11var FORMAT =12 'Browserslist config should be a string or an array ' +13 'of strings with browser queries'14var PATHTYPE_UNKNOWN = 'unknown'15var PATHTYPE_DIR = 'directory'16var PATHTYPE_FILE = 'file'17 18var dataTimeChecked = false19var statCache = {}20var configPathCache = {}21var parseConfigCache = {}22 23function checkExtend(name) {24 var use = ' Use `dangerousExtend` option to disable.'25 if (!CONFIG_PATTERN.test(name) && !SCOPED_CONFIG__PATTERN.test(name)) {26 throw new BrowserslistError(27 'Browserslist config needs `browserslist-config-` prefix. ' + use28 )29 }30 if (name.replace(/^@[^/]+\//, '').indexOf('.') !== -1) {31 throw new BrowserslistError(32 '`.` not allowed in Browserslist config name. ' + use33 )34 }35 if (name.indexOf('node_modules') !== -1) {36 throw new BrowserslistError(37 '`node_modules` not allowed in Browserslist config.' + use38 )39 }40}41 42function getPathType(filepath) {43 var stats44 try {45 stats = fs.existsSync(filepath) && fs.statSync(filepath)46 } catch (err) {47 /* c8 ignore start */48 if (49 err.code !== 'ENOENT' &&50 err.code !== 'EACCES' &&51 err.code !== 'ERR_ACCESS_DENIED'52 ) {53 throw err54 }55 /* c8 ignore end */56 }57 58 if (stats && stats.isDirectory()) return PATHTYPE_DIR59 if (stats && stats.isFile()) return PATHTYPE_FILE60 61 return PATHTYPE_UNKNOWN62}63 64function isFile(file) {65 return getPathType(file) === PATHTYPE_FILE66}67 68function isDirectory(dir) {69 return getPathType(dir) === PATHTYPE_DIR70}71 72function eachParent(file, callback, cache) {73 var loc = path.resolve(file)74 var pathsForCacheResult = []75 var result76 do {77 if (!pathInRoot(loc)) {78 break79 }80 if (cache && loc in cache) {81 result = cache[loc]82 break83 }84 pathsForCacheResult.push(loc)85 86 if (!isDirectory(loc)) {87 continue88 }89 90 var locResult = callback(loc)91 if (typeof locResult !== 'undefined') {92 result = locResult93 break94 }95 } while (loc !== (loc = path.dirname(loc)))96 97 if (cache && !process.env.BROWSERSLIST_DISABLE_CACHE) {98 pathsForCacheResult.forEach(function (cachePath) {99 cache[cachePath] = result100 })101 }102 return result103}104 105function pathInRoot(p) {106 if (!process.env.BROWSERSLIST_ROOT_PATH) return true107 var rootPath = path.resolve(process.env.BROWSERSLIST_ROOT_PATH)108 if (path.relative(rootPath, p).substring(0, 2) === '..') {109 return false110 }111 return true112}113 114function check(section) {115 if (Array.isArray(section)) {116 for (var i = 0; i < section.length; i++) {117 if (typeof section[i] !== 'string') {118 throw new BrowserslistError(FORMAT)119 }120 }121 } else if (typeof section !== 'string') {122 throw new BrowserslistError(FORMAT)123 }124}125 126function pickEnv(config, opts) {127 if (typeof config !== 'object') return config128 129 var name130 if (typeof opts.env === 'string') {131 name = opts.env132 } else if (process.env.BROWSERSLIST_ENV) {133 name = process.env.BROWSERSLIST_ENV134 } else if (process.env.NODE_ENV) {135 name = process.env.NODE_ENV136 } else {137 name = 'production'138 }139 140 if (opts.throwOnMissing) {141 if (name && name !== 'defaults' && !config[name]) {142 throw new BrowserslistError(143 'Missing config for Browserslist environment `' + name + '`'144 )145 }146 }147 148 return config[name] || config.defaults149}150 151function parsePackage(file) {152 var text = fs153 .readFileSync(file)154 .toString()155 .replace(/^\uFEFF/m, '')156 var list157 if (text.indexOf('"browserslist"') >= 0) {158 list = JSON.parse(text).browserslist159 } else if (text.indexOf('"browserlist"') >= 0) {160 var config = JSON.parse(text)161 if (config.browserlist && !config.browserslist) {162 throw new BrowserslistError(163 '`browserlist` key instead of `browserslist` in ' + file164 )165 }166 }167 if (Array.isArray(list) || typeof list === 'string') {168 list = { defaults: list }169 }170 for (var i in list) {171 check(list[i])172 }173 174 return list175}176 177function parsePackageOrReadConfig(file) {178 if (file in parseConfigCache) {179 return parseConfigCache[file]180 }181 182 var isPackage = path.basename(file) === 'package.json'183 var result = isPackage ? parsePackage(file) : module.exports.readConfig(file)184 185 if (!process.env.BROWSERSLIST_DISABLE_CACHE) {186 parseConfigCache[file] = result187 }188 return result189}190 191function latestReleaseTime(agents) {192 var latest = 0193 for (var name in agents) {194 var dates = agents[name].releaseDate || {}195 for (var key in dates) {196 if (latest < dates[key]) {197 latest = dates[key]198 }199 }200 }201 return latest * 1000202}203 204function getMonthsPassed(date) {205 var now = new Date()206 var past = new Date(date)207 208 var years = now.getFullYear() - past.getFullYear()209 var months = now.getMonth() - past.getMonth()210 211 return years * 12 + months212}213 214function normalizeStats(data, stats) {215 if (!data) {216 data = {}217 }218 if (stats && 'dataByBrowser' in stats) {219 stats = stats.dataByBrowser220 }221 222 if (typeof stats !== 'object') return undefined223 224 var normalized = {}225 for (var i in stats) {226 var versions = Object.keys(stats[i])227 if (versions.length === 1 && data[i] && data[i].versions.length === 1) {228 var normal = data[i].versions[0]229 normalized[i] = {}230 normalized[i][normal] = stats[i][versions[0]]231 } else {232 normalized[i] = stats[i]233 }234 }235 236 return normalized237}238 239function normalizeUsageData(usageData, data) {240 for (var browser in usageData) {241 var browserUsage = usageData[browser]242 // https://github.com/browserslist/browserslist/issues/431#issuecomment-565230615243 // caniuse-db returns { 0: "percentage" } for `and_*` regional stats244 if ('0' in browserUsage) {245 var versions = data[browser].versions246 browserUsage[versions[versions.length - 1]] = browserUsage[0]247 delete browserUsage[0]248 }249 }250}251 252module.exports = {253 loadQueries: function loadQueries(ctx, name) {254 if (!ctx.dangerousExtend && !process.env.BROWSERSLIST_DANGEROUS_EXTEND) {255 checkExtend(name)256 }257 var queries = require(require.resolve(name, { paths: ['.', ctx.path] }))258 if (typeof queries === 'object' && queries !== null && queries.__esModule) {259 queries = queries.default260 }261 if (queries) {262 if (Array.isArray(queries)) {263 return queries264 } else if (typeof queries === 'object') {265 if (!queries.defaults) queries.defaults = []266 return pickEnv(queries, ctx, name)267 }268 }269 throw new BrowserslistError(270 '`' +271 name +272 '` config exports not an array of queries' +273 ' or an object of envs'274 )275 },276 277 loadStat: function loadStat(ctx, name, data) {278 if (!ctx.dangerousExtend && !process.env.BROWSERSLIST_DANGEROUS_EXTEND) {279 checkExtend(name)280 }281 var stats = require(282 // Use forward slashes for module paths, also on Windows.283 require.resolve(path.posix.join(name, 'browserslist-stats.json'), {284 paths: ['.']285 })286 )287 return normalizeStats(data, stats)288 },289 290 getStat: function getStat(opts, data) {291 var stats292 if (opts.stats) {293 stats = opts.stats294 } else if (process.env.BROWSERSLIST_STATS) {295 stats = process.env.BROWSERSLIST_STATS296 } else if (opts.path && path.resolve && fs.existsSync) {297 stats = eachParent(298 opts.path,299 function (dir) {300 var file = path.join(dir, 'browserslist-stats.json')301 return isFile(file) ? file : undefined302 },303 statCache304 )305 }306 if (typeof stats === 'string') {307 try {308 stats = JSON.parse(fs.readFileSync(stats))309 } catch (e) {310 throw new BrowserslistError("Can't read " + stats)311 }312 }313 return normalizeStats(data, stats)314 },315 316 loadConfig: function loadConfig(opts) {317 if (process.env.BROWSERSLIST) {318 return process.env.BROWSERSLIST319 } else if (opts.config || process.env.BROWSERSLIST_CONFIG) {320 var file = opts.config || process.env.BROWSERSLIST_CONFIG321 return pickEnv(parsePackageOrReadConfig(file), opts)322 } else if (opts.path) {323 return pickEnv(module.exports.findConfig(opts.path), opts)324 } else {325 return undefined326 }327 },328 329 loadCountry: function loadCountry(usage, country, data) {330 var code = country.replace(/[^\w-]/g, '')331 if (!usage[code]) {332 var compressed333 try {334 compressed = require('caniuse-lite/data/regions/' + code + '.js')335 } catch (e) {336 throw new BrowserslistError('Unknown region name `' + code + '`.')337 }338 var usageData = region(compressed)339 normalizeUsageData(usageData, data)340 usage[country] = {}341 for (var i in usageData) {342 for (var j in usageData[i]) {343 usage[country][i + ' ' + j] = usageData[i][j]344 }345 }346 }347 },348 349 loadFeature: function loadFeature(features, name) {350 name = name.replace(/[^\w-]/g, '')351 if (features[name]) return352 var compressed353 try {354 compressed = require('caniuse-lite/data/features/' + name + '.js')355 } catch (e) {356 throw new BrowserslistError('Unknown feature name `' + name + '`.')357 }358 var stats = feature(compressed).stats359 features[name] = {}360 for (var i in stats) {361 features[name][i] = {}362 for (var j in stats[i]) {363 features[name][i][j] = stats[i][j]364 }365 }366 },367 368 parseConfig: function parseConfig(string) {369 var result = { defaults: [] }370 var sections = ['defaults']371 372 string373 .toString()374 .replace(/#[^\n]*/g, '')375 .split(/\n|,/)376 .map(function (line) {377 return line.trim()378 })379 .filter(function (line) {380 return line !== ''381 })382 .forEach(function (line) {383 if (IS_SECTION.test(line)) {384 sections = line.match(IS_SECTION)[1].trim().split(' ')385 sections.forEach(function (section) {386 if (result[section]) {387 throw new BrowserslistError(388 'Duplicate section ' + section + ' in Browserslist config'389 )390 }391 result[section] = []392 })393 } else {394 sections.forEach(function (section) {395 result[section].push(line)396 })397 }398 })399 400 return result401 },402 403 readConfig: function readConfig(file) {404 if (!isFile(file)) {405 throw new BrowserslistError("Can't read " + file + ' config')406 }407 408 return module.exports.parseConfig(fs.readFileSync(file))409 },410 411 findConfigFile: function findConfigFile(from) {412 return eachParent(413 from,414 function (dir) {415 var config = path.join(dir, 'browserslist')416 var pkg = path.join(dir, 'package.json')417 var rc = path.join(dir, '.browserslistrc')418 419 var pkgBrowserslist420 if (isFile(pkg)) {421 try {422 pkgBrowserslist = parsePackage(pkg)423 } catch (e) {424 if (e.name === 'BrowserslistError') throw e425 console.warn(426 '[Browserslist] Could not parse ' + pkg + '. Ignoring it.'427 )428 }429 }430 431 if (isFile(config) && pkgBrowserslist) {432 throw new BrowserslistError(433 dir + ' contains both browserslist and package.json with browsers'434 )435 } else if (isFile(rc) && pkgBrowserslist) {436 throw new BrowserslistError(437 dir +438 ' contains both .browserslistrc and package.json with browsers'439 )440 } else if (isFile(config) && isFile(rc)) {441 throw new BrowserslistError(442 dir + ' contains both .browserslistrc and browserslist'443 )444 } else if (isFile(config)) {445 return config446 } else if (isFile(rc)) {447 return rc448 } else if (pkgBrowserslist) {449 return pkg450 }451 },452 configPathCache453 )454 },455 456 findConfig: function findConfig(from) {457 var configFile = this.findConfigFile(from)458 459 return configFile ? parsePackageOrReadConfig(configFile) : undefined460 },461 462 clearCaches: function clearCaches() {463 dataTimeChecked = false464 statCache = {}465 configPathCache = {}466 parseConfigCache = {}467 468 this.cache = {}469 },470 471 oldDataWarning: function oldDataWarning(agentsObj) {472 if (dataTimeChecked) return473 dataTimeChecked = true474 if (process.env.BROWSERSLIST_IGNORE_OLD_DATA) return475 476 var latest = latestReleaseTime(agentsObj)477 var monthsPassed = getMonthsPassed(latest)478 479 if (latest !== 0 && monthsPassed >= 6) {480 if (process.env.BROWSERSLIST_TRACE_WARNING) {481 console.info('Last browser release in DB: ' + String(new Date(latest)))482 console.trace()483 }484 485 var months = monthsPassed + ' ' + (monthsPassed > 1 ? 'months' : 'month')486 console.warn(487 'Browserslist: browsers data (caniuse-lite) is ' +488 months +489 ' old. Please run:\n' +490 ' npx update-browserslist-db@latest\n' +491 ' Why you should do it regularly: ' +492 'https://github.com/browserslist/update-db#readme'493 )494 }495 },496 497 currentNode: function currentNode() {498 return 'node ' + process.versions.node499 },500 501 env: process.env502}503 