source: imaps-frontend/node_modules/update-browserslist-db/index.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 9.6 KB
Line 
1let { existsSync, readFileSync, writeFileSync } = require('fs')
2let { execSync } = require('child_process')
3let { join } = require('path')
4let escalade = require('escalade/sync')
5let pico = require('picocolors')
6
7const { detectEOL, detectIndent } = require('./utils')
8
9function BrowserslistUpdateError(message) {
10 this.name = 'BrowserslistUpdateError'
11 this.message = message
12 this.browserslist = true
13 if (Error.captureStackTrace) {
14 Error.captureStackTrace(this, BrowserslistUpdateError)
15 }
16}
17
18BrowserslistUpdateError.prototype = Error.prototype
19
20// Check if HADOOP_HOME is set to determine if this is running in a Hadoop environment
21const IsHadoopExists = !!process.env.HADOOP_HOME
22const yarnCommand = IsHadoopExists ? 'yarnpkg' : 'yarn'
23
24/* c8 ignore next 3 */
25function defaultPrint(str) {
26 process.stdout.write(str)
27}
28
29function detectLockfile() {
30 let packageDir = escalade('.', (dir, names) => {
31 return names.indexOf('package.json') !== -1 ? dir : ''
32 })
33
34 if (!packageDir) {
35 throw new BrowserslistUpdateError(
36 'Cannot find package.json. ' +
37 'Is this the right directory to run `npx update-browserslist-db` in?'
38 )
39 }
40
41 let lockfileNpm = join(packageDir, 'package-lock.json')
42 let lockfileShrinkwrap = join(packageDir, 'npm-shrinkwrap.json')
43 let lockfileYarn = join(packageDir, 'yarn.lock')
44 let lockfilePnpm = join(packageDir, 'pnpm-lock.yaml')
45 let lockfileBun = join(packageDir, 'bun.lockb')
46
47 if (existsSync(lockfilePnpm)) {
48 return { file: lockfilePnpm, mode: 'pnpm' }
49 } else if (existsSync(lockfileBun)) {
50 return { file: lockfileBun, mode: 'bun' }
51 } else if (existsSync(lockfileNpm)) {
52 return { file: lockfileNpm, mode: 'npm' }
53 } else if (existsSync(lockfileYarn)) {
54 let lock = { file: lockfileYarn, mode: 'yarn' }
55 lock.content = readFileSync(lock.file).toString()
56 lock.version = /# yarn lockfile v1/.test(lock.content) ? 1 : 2
57 return lock
58 } else if (existsSync(lockfileShrinkwrap)) {
59 return { file: lockfileShrinkwrap, mode: 'npm' }
60 }
61 throw new BrowserslistUpdateError(
62 'No lockfile found. Run "npm install", "yarn install" or "pnpm install"'
63 )
64}
65
66function getLatestInfo(lock) {
67 if (lock.mode === 'yarn') {
68 if (lock.version === 1) {
69 return JSON.parse(
70 execSync(yarnCommand + ' info caniuse-lite --json').toString()
71 ).data
72 } else {
73 return JSON.parse(
74 execSync(yarnCommand + ' npm info caniuse-lite --json').toString()
75 )
76 }
77 }
78 if (lock.mode === 'pnpm') {
79 return JSON.parse(execSync('pnpm info caniuse-lite --json').toString())
80 }
81 if (lock.mode === 'bun') {
82 // TO-DO: No 'bun info' yet. Created issue: https://github.com/oven-sh/bun/issues/12280
83 return JSON.parse(execSync(' npm info caniuse-lite --json').toString())
84 }
85
86 return JSON.parse(execSync('npm show caniuse-lite --json').toString())
87}
88
89function getBrowsers() {
90 let browserslist = require('browserslist')
91 return browserslist().reduce((result, entry) => {
92 if (!result[entry[0]]) {
93 result[entry[0]] = []
94 }
95 result[entry[0]].push(entry[1])
96 return result
97 }, {})
98}
99
100function diffBrowsers(old, current) {
101 let browsers = Object.keys(old).concat(
102 Object.keys(current).filter(browser => old[browser] === undefined)
103 )
104 return browsers
105 .map(browser => {
106 let oldVersions = old[browser] || []
107 let currentVersions = current[browser] || []
108 let common = oldVersions.filter(v => currentVersions.includes(v))
109 let added = currentVersions.filter(v => !common.includes(v))
110 let removed = oldVersions.filter(v => !common.includes(v))
111 return removed
112 .map(v => pico.red('- ' + browser + ' ' + v))
113 .concat(added.map(v => pico.green('+ ' + browser + ' ' + v)))
114 })
115 .reduce((result, array) => result.concat(array), [])
116 .join('\n')
117}
118
119function updateNpmLockfile(lock, latest) {
120 let metadata = { latest, versions: [] }
121 let content = deletePackage(JSON.parse(lock.content), metadata)
122 metadata.content = JSON.stringify(content, null, detectIndent(lock.content))
123 return metadata
124}
125
126function deletePackage(node, metadata) {
127 if (node.dependencies) {
128 if (node.dependencies['caniuse-lite']) {
129 let version = node.dependencies['caniuse-lite'].version
130 metadata.versions[version] = true
131 delete node.dependencies['caniuse-lite']
132 }
133 for (let i in node.dependencies) {
134 node.dependencies[i] = deletePackage(node.dependencies[i], metadata)
135 }
136 }
137 if (node.packages) {
138 for (let path in node.packages) {
139 if (path.endsWith('/caniuse-lite')) {
140 metadata.versions[node.packages[path].version] = true
141 delete node.packages[path]
142 }
143 }
144 }
145 return node
146}
147
148let yarnVersionRe = /version "(.*?)"/
149
150function updateYarnLockfile(lock, latest) {
151 let blocks = lock.content.split(/(\n{2,})/).map(block => {
152 return block.split('\n')
153 })
154 let versions = {}
155 blocks.forEach(lines => {
156 if (lines[0].indexOf('caniuse-lite@') !== -1) {
157 let match = yarnVersionRe.exec(lines[1])
158 versions[match[1]] = true
159 if (match[1] !== latest.version) {
160 lines[1] = lines[1].replace(
161 /version "[^"]+"/,
162 'version "' + latest.version + '"'
163 )
164 lines[2] = lines[2].replace(
165 /resolved "[^"]+"/,
166 'resolved "' + latest.dist.tarball + '"'
167 )
168 if (lines.length === 4) {
169 lines[3] = latest.dist.integrity
170 ? lines[3].replace(
171 /integrity .+/,
172 'integrity ' + latest.dist.integrity
173 )
174 : ''
175 }
176 }
177 }
178 })
179 let content = blocks.map(lines => lines.join('\n')).join('')
180 return { content, versions }
181}
182
183function updateLockfile(lock, latest) {
184 if (!lock.content) lock.content = readFileSync(lock.file).toString()
185
186 let updatedLockFile
187 if (lock.mode === 'yarn') {
188 updatedLockFile = updateYarnLockfile(lock, latest)
189 } else {
190 updatedLockFile = updateNpmLockfile(lock, latest)
191 }
192 updatedLockFile.content = updatedLockFile.content.replace(
193 /\n/g,
194 detectEOL(lock.content)
195 )
196 return updatedLockFile
197}
198
199function updatePackageManually(print, lock, latest) {
200 let lockfileData = updateLockfile(lock, latest)
201 let caniuseVersions = Object.keys(lockfileData.versions).sort()
202 if (caniuseVersions.length === 1 && caniuseVersions[0] === latest.version) {
203 print(
204 'Installed version: ' +
205 pico.bold(pico.green(caniuseVersions[0])) +
206 '\n' +
207 pico.bold(pico.green('caniuse-lite is up to date')) +
208 '\n'
209 )
210 return
211 }
212
213 if (caniuseVersions.length === 0) {
214 caniuseVersions[0] = 'none'
215 }
216 print(
217 'Installed version' +
218 (caniuseVersions.length === 1 ? ': ' : 's: ') +
219 pico.bold(pico.red(caniuseVersions.join(', '))) +
220 '\n' +
221 'Removing old caniuse-lite from lock file\n'
222 )
223 writeFileSync(lock.file, lockfileData.content)
224
225 let install =
226 lock.mode === 'yarn' ? yarnCommand + ' add -W' : lock.mode + ' install'
227 print(
228 'Installing new caniuse-lite version\n' +
229 pico.yellow('$ ' + install + ' caniuse-lite') +
230 '\n'
231 )
232 try {
233 execSync(install + ' caniuse-lite')
234 } catch (e) /* c8 ignore start */ {
235 print(
236 pico.red(
237 '\n' +
238 e.stack +
239 '\n\n' +
240 'Problem with `' +
241 install +
242 ' caniuse-lite` call. ' +
243 'Run it manually.\n'
244 )
245 )
246 process.exit(1)
247 } /* c8 ignore end */
248
249 let del =
250 lock.mode === 'yarn' ? yarnCommand + ' remove -W' : lock.mode + ' uninstall'
251 print(
252 'Cleaning package.json dependencies from caniuse-lite\n' +
253 pico.yellow('$ ' + del + ' caniuse-lite') +
254 '\n'
255 )
256 execSync(del + ' caniuse-lite')
257}
258
259function updateWith(print, cmd) {
260 print('Updating caniuse-lite version\n' + pico.yellow('$ ' + cmd) + '\n')
261 try {
262 execSync(cmd)
263 } catch (e) /* c8 ignore start */ {
264 print(pico.red(e.stdout.toString()))
265 print(
266 pico.red(
267 '\n' +
268 e.stack +
269 '\n\n' +
270 'Problem with `' +
271 cmd +
272 '` call. ' +
273 'Run it manually.\n'
274 )
275 )
276 process.exit(1)
277 } /* c8 ignore end */
278}
279
280module.exports = function updateDB(print = defaultPrint) {
281 let lock = detectLockfile()
282 let latest = getLatestInfo(lock)
283
284 let listError
285 let oldList
286 try {
287 oldList = getBrowsers()
288 } catch (e) {
289 listError = e
290 }
291
292 print('Latest version: ' + pico.bold(pico.green(latest.version)) + '\n')
293
294 if (lock.mode === 'yarn' && lock.version !== 1) {
295 updateWith(print, yarnCommand + ' up -R caniuse-lite')
296 } else if (lock.mode === 'pnpm') {
297 updateWith(print, 'pnpm up caniuse-lite')
298 } else if (lock.mode === 'bun') {
299 updateWith(print, 'bun update caniuse-lite')
300 } else {
301 updatePackageManually(print, lock, latest)
302 }
303
304 print('caniuse-lite has been successfully updated\n')
305
306 let newList
307 if (!listError) {
308 try {
309 newList = getBrowsers()
310 } catch (e) /* c8 ignore start */ {
311 listError = e
312 } /* c8 ignore end */
313 }
314
315 if (listError) {
316 if (listError.message.includes("Cannot find module 'browserslist'")) {
317 print(
318 pico.gray(
319 'Install `browserslist` to your direct dependencies ' +
320 'to see target browser changes\n'
321 )
322 )
323 } else {
324 print(
325 pico.red(
326 '\n' +
327 listError.stack +
328 '\n\n' +
329 'Problem with browser list retrieval.\n' +
330 'Target browser changes won’t be shown.\n'
331 )
332 )
333 }
334 } else {
335 let changes = diffBrowsers(oldList, newList)
336 if (changes) {
337 print('\nTarget browser changes:\n')
338 print(changes + '\n')
339 } else {
340 print('\n' + pico.green('No target browser changes') + '\n')
341 }
342 }
343}
Note: See TracBrowser for help on using the repository browser.