Merge reduce-packages

Assorted clean up
This commit is contained in:
PressJump 2022-10-22 14:23:46 +11:00 committed by GitHub
commit 6b65704fdd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 924 additions and 833 deletions

View file

@ -3,12 +3,17 @@ module.exports = {
es2021: true,
node: true,
},
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:unicorn/recommended'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: ['@typescript-eslint'],
rules: {},
plugins: ['@typescript-eslint', 'unicorn'],
rules: {
'unicorn/no-process-exit': 0,
// We are currently using commonjs. If / when it becomes viable for us to
// switch to ESModules, we should consider enabling this rule
'unicorn/prefer-module': 0,
},
}

View file

@ -5,7 +5,6 @@
"main": "index.js",
"reveal": true,
"bin": {
"melon": "./dist/index.js",
"gluon": "./dist/index.js"
},
"scripts": {
@ -46,18 +45,17 @@
"commander": "^6.2.1",
"execa": "^5.1.1",
"fs-extra": "^10.0.0",
"glob": "^7.1.7",
"ini": "^3.0.0",
"is-apple-silicon": "trickypr/is-apple-silicon",
"listr": "^0.14.3",
"kleur": "^4.1.5",
"modern-async": "^1.1.2",
"picomatch": "^2.3.1",
"png-to-ico": "^2.1.4",
"prompts": "^2.4.1",
"rimraf": "^3.0.2",
"rustic": "^1.2.1",
"semver": "^7.3.7",
"sharp": "^0.30.7",
"tiny-glob": "^0.2.9",
"xmlbuilder2": "^3.0.2"
},
"devDependencies": {
@ -75,6 +73,7 @@
"@typescript-eslint/eslint-plugin": "^5.22.0",
"@typescript-eslint/parser": "^5.22.0",
"eslint": "^8.15.0",
"eslint-plugin-unicorn": "^44.0.2",
"jest": "^27.4.5",
"prettier": "^2.2.1",
"ts-jest": "^27.1.2",

View file

@ -1,6 +1,9 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
/* eslint-disable unicorn/no-await-expression-member */
import { Cmd } from './types'
export const commands: Cmd[] = [
@ -115,7 +118,7 @@ export const commands: Cmd[] = [
aliases: ['pack'],
description: 'Package the browser for distribution.',
requestController: async () =>
(await import('./commands/package')).melonPackage,
(await import('./commands/package')).gluonPackage,
},
{
cmd: 'reset',

View file

@ -10,11 +10,11 @@ import { configDispatch } from '../utils'
export const bootstrap = async () => {
log.info(`Bootstrapping ${config.name}...`)
const args = ['--application-choice', 'browser']
const arguments_ = ['--application-choice', 'browser']
console.debug(`Passing through to |mach bootstrap|`)
await configDispatch('./mach', {
args: ['bootstrap', ...args],
args: ['bootstrap', ...arguments_],
cwd: ENGINE_DIR,
})
}

View file

@ -2,8 +2,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import execa from 'execa'
import { existsSync, readFileSync, writeFileSync } from 'fs'
import { join, resolve } from 'path'
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
import { join, resolve } from 'node:path'
import { bin_name, config } from '..'
import { BUILD_TARGETS, CONFIGS_DIR, ENGINE_DIR } from '../constants'
import { internalMozconfg } from '../constants/mozconfig'
@ -33,7 +33,7 @@ const applyConfig = async (os: string) => {
// Retrieve changeset
const { stdout } = await execa('git', ['rev-parse', 'HEAD'])
changeset = stdout.trim()
} catch (e) {
} catch (error) {
log.warning(
'Gluon expects that you are building your browser with git as your version control'
)
@ -43,15 +43,15 @@ const applyConfig = async (os: string) => {
log.warning('Otherwise, you can setup git in this folder by running:')
log.warning(' |git init|')
throw e
throw error
}
const templateOptions = {
name: config.name,
vendor: config.name,
appId: config.appId,
brandingDir: existsSync(join(ENGINE_DIR, 'branding', 'melon'))
? 'branding/melon'
brandingDir: existsSync(join(ENGINE_DIR, 'branding', 'gluon'))
? 'branding/gluon'
: 'branding/unofficial',
binName: config.binaryName,
changeset,

View file

@ -2,8 +2,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import execa from 'execa'
import { existsSync, statSync } from 'fs'
import { resolve } from 'path'
import { existsSync, statSync } from 'node:fs'
import { resolve } from 'node:path'
import { log } from '../log'
import { ENGINE_DIR } from '../constants'
@ -17,7 +17,7 @@ export const discard = async (file: string): Promise<void> => {
try {
await execa('git', ['restore', file], { cwd: ENGINE_DIR })
} catch (e) {
} catch {
log.warning(`The file ${file} was not changed`)
}
}

View file

@ -1,5 +1,5 @@
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'fs'
import { join } from 'path'
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'
import { isMatch } from 'picomatch'
import { config } from '../..'
@ -10,7 +10,7 @@ import {
AddonInfo,
configDispatch,
delay,
ensureDir,
ensureDirectory,
walkDirectoryTree,
windowsPathToUnix,
} from '../../utils'
@ -29,31 +29,52 @@ export async function resolveAddonDownloadUrl(
addon: AddonInfo
): Promise<string> {
switch (addon.platform) {
case 'url':
case 'url': {
return addon.url
}
case 'amo':
return (
await axios.get(
case 'amo': {
try {
const mozillaData = await axios.get(
`https://addons.mozilla.org/api/v4/addons/addon/${addon.amoId}/versions/`
)
).data.results[0].files[0].url
case 'github':
return (
(
((
await axios.get(
`https://api.github.com/repos/${addon.repo}/releases/tags/${addon.version}`
)
).data.assets as {
url: string
browser_download_url: string
name: string
}[]) || []
).find((asset) => isMatch(asset.name, addon.fileGlob))
?.browser_download_url || 'failed'
)
return mozillaData.data.results[0].files[0].url
} catch (error) {
log.warning(
'The following error occured whilst fetching amo addon metadata'
)
log.error(error)
return ''
}
}
case 'github': {
try {
const githubData = await axios.get(
`https://api.github.com/repos/${addon.repo}/releases/tags/${addon.version}`
)
return (
(
(githubData.data.assets as {
url: string
browser_download_url: string
name: string
}[]) || []
).find((asset) => isMatch(asset.name, addon.fileGlob))
?.browser_download_url || 'failed'
)
} catch (error) {
log.warning(
'The following error occured whilst fetching github metadata'
)
log.error(error)
return ''
}
}
}
}
@ -61,7 +82,7 @@ export async function downloadAddon(
url: string,
addon: AddonInfo & { name: string }
): Promise<string> {
const tempFile = join(MELON_TMP_DIR, addon.name + '.xpi')
const temporaryFile = join(MELON_TMP_DIR, addon.name + '.xpi')
log.info(`Download addon from ${url}`)
@ -73,23 +94,23 @@ export async function downloadAddon(
// it
} else {
const cache = extensionCache.unwrap()
if (cache.url == url && existsSync(tempFile)) {
if (cache.url == url && existsSync(temporaryFile)) {
log.info(`Using cached version of ${addon.name}`)
return tempFile
return temporaryFile
}
}
}
if (existsSync(tempFile)) {
unlinkSync(tempFile)
if (existsSync(temporaryFile)) {
unlinkSync(temporaryFile)
}
await downloadFileToLocation(url, tempFile)
await downloadFileToLocation(url, temporaryFile)
// I do not know why, but this delay causes unzip to work reliably
await delay(200)
return tempFile
return temporaryFile
}
export async function unpackAddon(
@ -110,7 +131,7 @@ export async function unpackAddon(
// I do not know why, but this delay causes unzip to work reliably
await delay(200)
ensureDir(outPath)
ensureDirectory(outPath)
await configDispatch('unzip', {
args: [windowsPathToUnix(path), '-d', windowsPathToUnix(outPath)],

View file

@ -1,12 +1,12 @@
import execa from 'execa'
import { existsSync } from 'fs'
import { dirname, resolve } from 'path'
import { existsSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { bin_name } from '../..'
import { BASH_PATH, ENGINE_DIR, MELON_TMP_DIR } from '../../constants'
import { log } from '../../log'
import { commandExistsSync } from '../../utils/commandExists'
import { commandExistsSync } from '../../utils/command-exists'
import { downloadFileToLocation } from '../../utils/download'
import { ensureDir, windowsPathToUnix } from '../../utils/fs'
import { ensureDirectory, windowsPathToUnix } from '../../utils/fs'
import { init } from '../init'
export function shouldSetupFirefoxSource() {
@ -30,7 +30,7 @@ export async function setupFirefoxSource(version: string) {
async function unpackFirefoxSource(name: string): Promise<void> {
log.info(`Unpacking Firefox...`)
ensureDir(ENGINE_DIR)
ensureDirectory(ENGINE_DIR)
let tarExec = 'tar'
@ -56,12 +56,12 @@ async function unpackFirefoxSource(name: string): Promise<void> {
tarExec,
[
'--strip-components=1',
process.platform == 'win32' ? '--force-local' : null,
process.platform == 'win32' ? '--force-local' : undefined,
'-xf',
windowsPathToUnix(resolve(MELON_TMP_DIR, name)),
'-C',
windowsPathToUnix(ENGINE_DIR),
].filter((x) => x) as string[],
].filter(Boolean) as string[],
{
// HACK: Use bash shell on windows to get a sane version of tar that works
shell: BASH_PATH || false,
@ -80,7 +80,7 @@ async function downloadFirefoxSource(version: string) {
log.info(`Locating Firefox release ${version}...`)
await ensureDir(dirname(fsSaveLocation))
await ensureDirectory(dirname(fsSaveLocation))
if (existsSync(fsSaveLocation)) {
log.info('Using cached download')

View file

@ -1,26 +1,26 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { existsSync } from 'fs'
import { existsSync } from 'node:fs'
import { log } from '../log'
import { ENGINE_DIR } from '../constants'
import { dispatch } from '../utils'
export const execute = async (cmd: string[]) => {
if (existsSync(ENGINE_DIR)) {
if (!cmd || cmd.length == 0)
if (!cmd || cmd.length === 0)
log.error('You need to specify a command to run.')
const bin = cmd[0]
const args = cmd
args.shift()
const arguments_ = cmd
arguments_.shift()
log.info(
`Executing \`${bin}${args.length !== 0 ? ` ` : ``}${args.join(
`Executing \`${bin}${arguments_.length > 0 ? ` ` : ``}${arguments_.join(
' '
)}\` in \`src\`...`
)
dispatch(bin, args, ENGINE_DIR)
dispatch(bin, arguments_, ENGINE_DIR)
} else {
log.error(`Unable to locate src directory.`)
}

View file

@ -2,11 +2,11 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import execa from 'execa'
import { existsSync, writeFileSync } from 'fs'
import { basename, resolve } from 'path'
import { existsSync, writeFileSync } from 'node:fs'
import { basename, resolve } from 'node:path'
import { log } from '../log'
import { ENGINE_DIR, SRC_DIR } from '../constants'
import { delay, ensureDir } from '../utils'
import { delay, ensureDirectory } from '../utils'
export const getPatchName = (file: string): string =>
`${basename(file).replace(/\./g, '-')}.patch`
@ -36,7 +36,7 @@ export const exportFile = async (file: string): Promise<void> => {
const name = getPatchName(file)
const patchPath = file.replace(/\./g, '-').split('/').slice(0, -1)
await ensureDir(resolve(SRC_DIR, ...patchPath))
await ensureDirectory(resolve(SRC_DIR, ...patchPath))
if (proc.stdout.length >= 8000) {
log.warning('')

View file

@ -2,8 +2,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { Command } from 'commander'
import { existsSync, readFileSync } from 'fs'
import { resolve } from 'path'
import { existsSync, readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { bin_name } from '..'
import { log } from '../log'
import { config, configDispatch } from '../utils'
@ -11,9 +11,9 @@ import { config, configDispatch } from '../utils'
export const init = async (directory: Command | string): Promise<void> => {
const cwd = process.cwd()
const dir = resolve(cwd as string, directory.toString())
const absoluteInitDirectory = resolve(cwd as string, directory.toString())
if (!existsSync(dir)) {
if (!existsSync(absoluteInitDirectory)) {
log.error(
`Directory "${directory}" not found.\nCheck the directory exists and run |${bin_name} init| again.`
)
@ -36,30 +36,31 @@ export const init = async (directory: Command | string): Promise<void> => {
version = version.trim().replace(/\\n/g, '')
// TODO: Use bash on windows, this may significantly improve performance. Still needs testing though
// TODO: Use bash on windows, this may significantly improve performance.
// Still needs testing though
log.info('Initializing git, this may take some time')
await configDispatch('git', {
args: ['init'],
cwd: dir,
cwd: absoluteInitDirectory,
shell: 'unix',
})
await configDispatch('git', {
args: ['init'],
cwd: dir,
cwd: absoluteInitDirectory,
shell: 'unix',
})
await configDispatch('git', {
args: ['checkout', '--orphan', version],
cwd: dir,
cwd: absoluteInitDirectory,
shell: 'unix',
})
await configDispatch('git', {
args: ['add', '-f', '.'],
cwd: dir,
cwd: absoluteInitDirectory,
shell: 'unix',
})
@ -67,13 +68,13 @@ export const init = async (directory: Command | string): Promise<void> => {
await configDispatch('git', {
args: ['commit', '-aqm', `"Firefox ${version}"`],
cwd: dir,
cwd: absoluteInitDirectory,
shell: 'unix',
})
await configDispatch('git', {
args: ['checkout', '-b', config.name.toLowerCase().replace(/\s/g, '_')],
cwd: dir,
cwd: absoluteInitDirectory,
shell: 'unix',
})
}

View file

@ -2,7 +2,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { join } from 'path'
import { join } from 'node:path'
import { isValidLicense } from './license-check'
describe('isValidLicense', () => {

View file

@ -1,12 +1,12 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { readFile, writeFile } from 'fs/promises'
import Listr, { ListrTask } from 'listr'
import { join } from 'path'
import { readFile, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { SRC_DIR } from '../constants'
import { walkDirectory } from '../utils/fs'
import { Task, TaskList } from '../utils/task-list'
const ignoredFiles = new RegExp('.*\\.(json|patch|md|jpeg|png|gif|tiff|ico)')
const licenseIgnore = new RegExp('(//|#) Ignore license in this file', 'g')
@ -25,14 +25,14 @@ const fixableFiles = [
commentClose: '\n -->',
},
{
regex: new RegExp('.*\\.py|moz\\.build'),
regex: new RegExp('.*\\.py|moz\\.build|jar\\.mn'),
comment: '# ',
commentClose: '\n',
},
]
export async function isValidLicense(path: string): Promise<boolean> {
const file = (await readFile(path)).toString()
const file = await readFile(path, { encoding: 'utf8' })
const contents = file.split('\n')
// We need to grab the top 5 lines just in case there are newlines in the
@ -53,57 +53,54 @@ export async function isValidLicense(path: string): Promise<boolean> {
return hasLicense
}
export function listrCheckFile(
path: string,
noFix: boolean
): ListrTask<unknown> {
export function createTask(path: string, noFix: boolean): Task {
return {
skip: () => ignoredFiles.test(path),
title: path.replace(SRC_DIR, ''),
name: path.replace(SRC_DIR, ''),
task: async () => {
const contents = (await readFile(path)).toString().split('\n')
const contents = await readFile(path, { encoding: 'utf8' })
const contentsSplitNewline = contents.split('\n')
const hasLicense = await isValidLicense(path)
if (!hasLicense) {
const fixable = fixableFiles.find(({ regex }) => regex.test(path))
if (!fixable || noFix) {
throw new Error(
`${path} does not have a license. Please add the source code header`
)
} else {
const mpl = (
await readFile(join(__dirname, 'license-check.txt'))
).toString()
const { comment, commentOpen, commentClose } = fixable
let header = mpl
.split('\n')
.map((ln) => (comment || '') + ln)
.join('\n')
if (commentOpen) {
header = commentOpen + header + commentClose
}
await writeFile(path, header + '\n' + contents.join('\n'))
}
if (hasLicense) {
return
}
const fixable = fixableFiles.find(({ regex }) => regex.test(path))
if (!fixable || noFix) {
throw new Error(
`${path} does not have a license. Please add the source code header`
)
}
const mplHeader = // eslint-disable-next-line unicorn/prefer-module
await readFile(join(__dirname, 'license-check.txt'), {
encoding: 'utf8',
})
const { comment, commentOpen, commentClose } = fixable
let header = mplHeader
.split('\n')
.map((ln) => (comment || '') + ln)
.join('\n')
if (commentOpen) {
header = commentOpen + header + commentClose
}
await writeFile(path, header + '\n' + contentsSplitNewline.join('\n'))
},
}
}
interface Options {
noFix: boolean
fix: boolean
}
export const licenseCheck = async (options: Options): Promise<void> => {
const files = await walkDirectory(SRC_DIR)
await new Listr(
files.map((file) => listrCheckFile(file, options.noFix)),
{
concurrent: true,
exitOnError: false,
}
).run()
await new TaskList(files.map((file) => createTask(file, !options.fix)))
.onError('inline')
.run()
}

View file

@ -1,9 +1,9 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { existsSync } from 'fs'
import { copyFile, mkdir, readdir, unlink } from 'fs/promises'
import { join, resolve } from 'path'
import { existsSync } from 'node:fs'
import { copyFile, mkdir, readdir, unlink } from 'node:fs/promises'
import { join, resolve } from 'node:path'
import { bin_name, config } from '..'
import { DIST_DIR, ENGINE_DIR, OBJ_DIR } from '../constants'
@ -18,7 +18,7 @@ import { generateBrowserUpdateFiles } from './updates/browser'
const machPath = resolve(ENGINE_DIR, 'mach')
export const melonPackage = async () => {
export const gluonPackage = async () => {
const brandingKey = dynamicConfig.get('brand') as string
const brandingDetails = config.brands[brandingKey]
@ -37,15 +37,15 @@ export const melonPackage = async () => {
log.error(`Cannot locate the 'mach' binary within ${ENGINE_DIR}`)
}
const args = ['package']
const arguments_ = ['package']
log.info(
`Packaging \`${config.binaryName}\` with args ${JSON.stringify(
args.slice(1, 0)
arguments_.slice(1, 0)
)}...`
)
await dispatch(machPath, args, ENGINE_DIR, true)
await dispatch(machPath, arguments_, ENGINE_DIR, true)
log.info('Copying results up')
@ -53,31 +53,41 @@ export const melonPackage = async () => {
if (!existsSync(DIST_DIR)) await mkdir(DIST_DIR, { recursive: true })
log.debug('Indexing files to copy')
const files = (await readdir(join(OBJ_DIR, 'dist'), { withFileTypes: true }))
const filesInMozillaDistrobution = await readdir(join(OBJ_DIR, 'dist'), {
withFileTypes: true,
})
const files = filesInMozillaDistrobution
.filter((entry) => entry.isFile())
.map((entry) => entry.name)
for (const file of files) {
const destFile = join(DIST_DIR, file)
const destinationFile = join(DIST_DIR, file)
log.debug(`Copying ${file}`)
if (existsSync(destFile)) await unlink(destFile)
await copyFile(join(OBJ_DIR, 'dist', file), destFile)
if (existsSync(destinationFile)) await unlink(destinationFile)
await copyFile(join(OBJ_DIR, 'dist', file), destinationFile)
}
// Windows has some special dist files that are available within the dist
// directory.
if (process.platform == 'win32') {
const installerDistDirectory = join(OBJ_DIR, 'dist', 'install', 'sea')
const installerDistributionDirectory = join(
OBJ_DIR,
'dist',
'install',
'sea'
)
if (!existsSync(installerDistDirectory)) {
if (!existsSync(installerDistributionDirectory)) {
log.error(
`Could not find windows installer files located at '${installerDistDirectory}'`
`Could not find windows installer files located at '${installerDistributionDirectory}'`
)
}
const windowsInstallerFiles = (
await readdir(installerDistDirectory, { withFileTypes: true })
const installerDistributionDirectoryContents = await readdir(
installerDistributionDirectory,
{ withFileTypes: true }
)
const windowsInstallerFiles = installerDistributionDirectoryContents
.filter((entry) => entry.isFile())
.map((entry) => entry.name)
@ -96,10 +106,13 @@ export const melonPackage = async () => {
}
// Actually copy
const destFile = join(DIST_DIR, newFileName)
const destinationFile = join(DIST_DIR, newFileName)
log.debug(`Copying ${file}`)
if (existsSync(destFile)) await unlink(destFile)
await copyFile(join(installerDistDirectory, file), destFile)
if (existsSync(destinationFile)) await unlink(destinationFile)
await copyFile(
join(installerDistributionDirectory, file),
destinationFile
)
}
}
@ -137,18 +150,10 @@ async function createMarFile(version: string, channel: string) {
// On macos this should be
// <obj dir>/dist/${binaryName}/${brandFullName}.app and on everything else,
// the contents of the folder <obj dir>/dist/${binaryName}
let binary: string
if (process.platform == 'darwin') {
binary = join(
OBJ_DIR,
'dist',
config.binaryName,
`${getCurrentBrandName()}.app`
)
} else {
binary = join(OBJ_DIR, 'dist', config.binaryName)
}
const binary =
process.platform == 'darwin'
? join(OBJ_DIR, 'dist', config.binaryName, `${getCurrentBrandName()}.app`)
: join(OBJ_DIR, 'dist', config.binaryName)
const marPath = windowsPathToUnix(join(DIST_DIR, 'output.mar'))
await configDispatch('./tools/update-packaging/make_full_update.sh', {

View file

@ -10,10 +10,10 @@ import {
readFileSync,
writeFileSync,
copyFileSync,
} from 'fs'
import { copyFile, readFile, rm, writeFile } from 'fs/promises'
} from 'node:fs'
import { copyFile, mkdir, readFile, rm, writeFile } from 'node:fs/promises'
import { every } from 'modern-async'
import { dirname, extname, join } from 'path'
import { dirname, extname, join } from 'node:path'
import sharp from 'sharp'
import pngToIco from 'png-to-ico'
import asyncIcns from 'async-icns'
@ -31,7 +31,7 @@ import {
walkDirectory,
windowsPathToUnix,
} from '../../utils'
import { templateDir } from '../setup-project'
import { templateDirectory } from '../setup-project'
import { IMelonPatch } from './command'
// =============================================================================
@ -74,7 +74,7 @@ function constructConfig(name: string) {
brandingVendor: config.vendor,
...defaultBrandsConfig,
...(config.brands[name] || {}),
...config.brands[name],
}
}
@ -111,15 +111,15 @@ async function setupImages(configPath: string, outputPath: string) {
// TODO: Custom MacOS icon support
if (process.platform == 'darwin') {
log.debug('Generating Mac Icons')
const tmp = join(MELON_TMP_DIR, 'macos_icon_info.iconset')
const temporary = join(MELON_TMP_DIR, 'macos_icon_info.iconset')
if (existsSync(tmp)) await rm(tmp, { recursive: true })
if (existsSync(temporary)) await rm(temporary, { recursive: true })
asyncIcns.convert({
input: join(configPath, 'logo.png'),
output: join(outputPath, 'firefox.icns'),
sizes: [16, 32, 64, 128, 256, 512],
tmpDirectory: tmp,
tmpDirectory: temporary,
})
}
@ -155,22 +155,32 @@ async function setupLocale(
brandingVendor: string
}
) {
// eslint-disable-next-line @typescript-eslint/no-extra-semi
;(await walkDirectory(join(templateDir, 'branding.optional')))
.map((file) =>
windowsPathToUnix(file).replace(
windowsPathToUnix(join(templateDir, 'branding.optional') + '/'),
''
)
)
.map((file) => [
readFileSync(join(templateDir, 'branding.optional', file)).toString(),
join(outputPath, file),
])
.forEach(([contents, path]) => {
mkdirSync(dirname(path), { recursive: true })
writeFileSync(path, stringTemplate(contents, brandingConfig))
for (const file of await walkDirectory(
join(templateDirectory, 'branding.optional')
)) {
const fileContents = await readFile(windowsPathToUnix(file), {
encoding: 'utf8',
})
const universalPath =
// We want to avoid the pain that windows is going to throw at us with its
// weird paths
windowsPathToUnix(file)
// We want to remove all of the extra folders that surround this from the
// template folder
.replace(
windowsPathToUnix(join(templateDirectory, 'branding.optional') + '/'),
''
)
const sourceFolderPath = join(outputPath, universalPath)
await mkdir(dirname(sourceFolderPath), { recursive: true })
await writeFile(
sourceFolderPath,
stringTemplate(fileContents, brandingConfig)
)
}
}
async function copyMozFiles(
@ -184,7 +194,8 @@ async function copyMozFiles(
brandingVendor: string
}
) {
const files = (await walkDirectory(BRANDING_FF)).filter(
const firefoxBrandingDirectoryContents = await walkDirectory(BRANDING_FF)
const files = firefoxBrandingDirectoryContents.filter(
(file) => !existsSync(join(outputPath, file.replace(BRANDING_FF, '')))
)
@ -192,7 +203,7 @@ async function copyMozFiles(
const everythingElse = files.filter((file) => !css.includes(file))
css
for (const [contents, path] of css
.map((filePath) => [
readFileSync(filePath).toString(),
join(outputPath, filePath.replace(BRANDING_FF, '')),
@ -201,17 +212,16 @@ async function copyMozFiles(
contents.replace(CSS_REPLACE_REGEX, 'var(--theme-bg)') +
`:root { --theme-bg: ${brandingConfig.backgroundColor} }`,
path,
])
.forEach(([contents, path]) => {
mkdirSync(dirname(path), { recursive: true })
writeFileSync(path, contents)
})
])) {
mkdirSync(dirname(path), { recursive: true })
writeFileSync(path, contents)
}
// Copy everything else from the default firefox branding directory
everythingElse.forEach((file) => {
for (const file of everythingElse) {
mkdirpSync(dirname(join(outputPath, file.replace(BRANDING_FF, ''))))
copyFileSync(file, join(outputPath, file.replace(BRANDING_FF, '')))
})
}
}
// =============================================================================

View file

@ -1,48 +1,45 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { sync } from 'glob'
import Listr from 'listr'
import { ENGINE_DIR, SRC_DIR } from '../../constants'
import { join } from 'node:path'
import { existsSync } from 'node:fs'
import glob from 'tiny-glob'
import * as gitPatch from './gitPatch'
import * as copyPatch from './copyPatches'
import * as brandingPatch from './brandingPatch'
import { join } from 'path'
import { existsSync, writeFileSync } from 'fs'
import { ENGINE_DIR, SRC_DIR } from '../../constants'
import * as gitPatch from './git-patch'
import * as copyPatch from './copy-patches'
import * as brandingPatch from './branding-patch'
import { patchCountFile } from '../../middleware/patch-check'
import { checkHash } from '../../utils'
import { log } from '../../log'
import { templateDir } from '../setup-project'
type ListrTaskGroup = Listr.ListrTask<unknown>
import { templateDirectory } from '../setup-project'
import { Task, TaskList } from '../../utils/task-list'
import { writeFile } from 'node:fs/promises'
export interface IMelonPatch {
name: string
skip?: (
ctx: unknown
) => string | boolean | void | Promise<string | boolean | undefined>
skip?: () => boolean | Promise<boolean>
}
function patchMethod<T extends IMelonPatch>(
name: string,
patches: T[],
patchFn: (patch: T, index: number) => Promise<void>
): ListrTaskGroup {
patchFunction: (patch: T, index: number) => Promise<void>
): Task {
return {
title: `Apply ${patches.length} ${name} patches`,
name: `Apply ${patches.length} ${name} patches`,
long: true,
task: () =>
new Listr(
new TaskList(
patches.map((patch, index) => ({
title: `Apply ${patch.name}`,
task: () => patchFn(patch, index),
name: `Apply ${patch.name}`,
task: () => patchFunction(patch, index),
skip: patch.skip,
}))
),
}
}
function importMelonPatches(): ListrTaskGroup {
function importMelonPatches(): Task {
return patchMethod(
'branding',
[
@ -63,10 +60,10 @@ function importMelonPatches(): ListrTaskGroup {
(await macosInstallerCheck) &&
existsSync(join(ENGINE_DIR, 'browser/branding', name))
) {
return `${name} has already been applied`
return true
}
return
return false
},
})) as brandingPatch.IBrandingPatch[]),
],
@ -74,20 +71,22 @@ function importMelonPatches(): ListrTaskGroup {
)
}
function importFolders(): ListrTaskGroup {
async function importFolders(): Promise<Task> {
return patchMethod(
'folder',
copyPatch.get(),
await copyPatch.get(),
async (patch) => await copyPatch.apply(patch.src)
)
}
function importGitPatch(): ListrTaskGroup {
const patches = sync('**/*.patch', { nodir: true, cwd: SRC_DIR }).map(
(path) => join(SRC_DIR, path)
)
async function importGitPatch(): Promise<Task> {
let patches = await glob('**/*.patch', {
filesOnly: true,
cwd: SRC_DIR,
})
patches = patches.map((path) => join(SRC_DIR, path))
writeFileSync(patchCountFile, patches.length.toString())
await writeFile(patchCountFile, patches.length.toString())
return patchMethod<gitPatch.IGitPatch>(
'git',
@ -96,32 +95,28 @@ function importGitPatch(): ListrTaskGroup {
)
}
function importInternalPatch(): ListrTaskGroup {
const patches = sync('*.patch', {
nodir: true,
cwd: join(templateDir, 'patches.optional'),
}).map((path) => ({
async function importInternalPatch(): Promise<Task> {
const patches = await glob('*.patch', {
filesOnly: true,
cwd: join(templateDirectory, 'patches.optional'),
})
const structuredPatches = patches.map((path) => ({
name: path,
path: join(templateDir, 'patches.optional', path),
path: join(templateDirectory, 'patches.optional', path),
}))
return patchMethod<gitPatch.IGitPatch>(
'gluon',
patches,
structuredPatches,
async (patch) => await gitPatch.apply(patch.path)
)
}
export async function applyPatches(): Promise<void> {
await new Listr(
[
importInternalPatch(),
importMelonPatches(),
importFolders(),
importGitPatch(),
],
{
renderer: log.isDebug ? 'verbose' : 'default',
}
).run()
await new TaskList([
await importInternalPatch(),
importMelonPatches(),
await importFolders(),
await importGitPatch(),
]).run()
}

View file

@ -1,13 +1,12 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { sync } from 'glob'
import { existsSync } from 'fs'
import { lstatSync, readFileSync } from 'fs'
import { ensureSymlink } from 'fs-extra'
import { copyFile } from 'fs/promises'
import { dirname, resolve } from 'path'
import rimraf from 'rimraf'
import { existsSync } from 'node:fs'
import { lstatSync, readFileSync } from 'node:fs'
import { ensureSymlink, remove } from 'fs-extra'
import { copyFile } from 'node:fs/promises'
import { dirname, resolve } from 'node:path'
import glob from 'tiny-glob'
import { appendToFileSync, mkdirp } from '../../utils'
import { config } from '../..'
@ -26,7 +25,7 @@ export const copyManual = async (name: string): Promise<void> => {
existsSync(resolve(ENGINE_DIR, ...getChunked(name))) &&
!lstatSync(resolve(ENGINE_DIR, ...getChunked(name))).isSymbolicLink()
) {
rimraf.sync(resolve(ENGINE_DIR, ...getChunked(name)))
await remove(resolve(ENGINE_DIR, ...getChunked(name)))
}
if (
@ -70,20 +69,21 @@ export interface ICopyPatch extends IMelonPatch {
// =============================================================================
// Exports
export function get(): ICopyPatch[] {
const files = sync('**/*', {
nodir: true,
export async function get(): Promise<ICopyPatch[]> {
const allFilesInSource = await glob('**/*', {
filesOnly: true,
cwd: SRC_DIR,
}).filter(
})
const files = allFilesInSource.filter(
(f) => !(f.endsWith('.patch') || f.split('/').includes('node_modules'))
)
const manualPatches: ICopyPatch[] = []
files.map((i) => {
const group = i.split('/')[0]
files.map((index) => {
const group = index.split('/')[0]
if (!manualPatches.find((m) => m.name == group)) {
if (!manualPatches.some((m) => m.name == group)) {
manualPatches.push({
name: group,
src: files.filter((f) => f.split('/')[0] == group),
@ -94,8 +94,8 @@ export function get(): ICopyPatch[] {
return manualPatches
}
export async function apply(src: string[]): Promise<void> {
for (const item of src) {
export async function apply(source: string[]): Promise<void> {
for (const item of source) {
await copyManual(item)
}
}

View file

@ -1,8 +1,10 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import execa from 'execa'
import { PATCH_ARGS, ENGINE_DIR } from '../../constants'
import { log } from '../../log'
import { IMelonPatch } from './command'
export interface IGitPatch extends IMelonPatch {
@ -14,11 +16,11 @@ export async function apply(path: string): Promise<void> {
await execa('git', ['apply', '-R', ...PATCH_ARGS, path], {
cwd: ENGINE_DIR,
})
} catch (_e) {
} catch {
// If the patch has already been applied, we want to revert it. Because
// there is no good way to check this we are just going to catch and
// discard the error
null
undefined
}
const { stdout, exitCode } = await execa(
@ -27,5 +29,5 @@ export async function apply(path: string): Promise<void> {
{ cwd: ENGINE_DIR }
)
if (exitCode != 0) throw stdout
if (exitCode != 0) log.error(stdout)
}

View file

@ -1,27 +1,29 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { existsSync, readdirSync } from 'fs'
import { resolve } from 'path'
import { existsSync, readdirSync } from 'node:fs'
import { resolve } from 'node:path'
import { bin_name } from '..'
import { ENGINE_DIR } from '../constants'
import { log } from '../log'
import { config, dispatch } from '../utils'
export const run = async (chrome?: string) => {
const dirs = readdirSync(ENGINE_DIR)
const objDirname = dirs.find((dir) => dir.startsWith('obj-'))
const directories = readdirSync(ENGINE_DIR)
const objectDirname = directories.find((directory) =>
directory.startsWith('obj-')
)
if (!objDirname) {
if (!objectDirname) {
throw new Error(`${config.name} needs to be built before you can do this.`)
}
const objDir = resolve(ENGINE_DIR, objDirname)
const objectDirectory = resolve(ENGINE_DIR, objectDirname)
if (existsSync(objDir)) {
if (existsSync(objectDirectory)) {
dispatch(
'./mach',
['run'].concat(chrome ? ['-chrome', chrome] : []),
['run', ...(chrome ? ['-chrome', chrome] : [])],
ENGINE_DIR,
true
)

View file

@ -1,9 +1,9 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { writeFileSync, existsSync, mkdirSync, readFileSync } from 'fs'
import { copyFile } from 'fs/promises'
import { join, dirname } from 'path'
import { writeFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs'
import { copyFile } from 'node:fs/promises'
import { join, dirname } from 'node:path'
import prompts from 'prompts'
import { bin_name } from '..'
@ -14,7 +14,7 @@ import {
configPath,
delay,
getLatestFF,
projectDir,
projectDirectory,
SupportedProducts,
walkDirectory,
} from '../utils'
@ -50,19 +50,13 @@ export async function setupProject(): Promise<void> {
{
title: 'Firefox extended support (older)',
description:
'The oldest supported extended support release. Maximum security and stability, but will lose support sooner than the newer extended support release.',
'The extended support version of Firefox. Will receive security updates for a longer period of time and less frequent, bigger, feature updates',
value: SupportedProducts.FirefoxESR,
},
{
title: 'Firefox extended support (newer)',
description:
'The latest extended support release. Releases around once every 8 stable cycles. Receives regular small security patches and bug fixes.',
value: SupportedProducts.FirefoxESRNext,
},
{
title: 'Firefox developer edition (Not recommended)',
description: 'Tracks firefox beta, with a few config tweaks',
value: SupportedProducts.FirefoxDev,
value: SupportedProducts.FirefoxDevelopment,
},
{
title: 'Firefox beta (Not recommended)',
@ -153,10 +147,10 @@ export async function setupProject(): Promise<void> {
await copyOptional(['browser/themes'])
}
writeFileSync(configPath, JSON.stringify(config, null, 2))
writeFileSync(configPath, JSON.stringify(config, undefined, 2))
// Append important stuff to gitignore
const gitignore = join(projectDir, '.gitignore')
const gitignore = join(projectDirectory, '.gitignore')
let gitignoreContents = ''
if (existsSync(gitignore)) {
@ -174,48 +168,64 @@ export async function setupProject(): Promise<void> {
`You can start downloading the Firefox source code by running |${bin_name} download|`,
'Or you can follow the getting started guide at https://docs.gluon.dev/getting-started/overview/'
)
} catch (e) {
log.error(e)
} catch (error) {
log.error(error)
}
}
// =============================================================================
// Filesystem templating
export const templateDir = join(__dirname, '../..', 'template')
// eslint-disable-next-line unicorn/prefer-module
export const templateDirectory = join(__dirname, '../..', 'template')
/**
* Copy files from the template directory that have .optional in their path,
* based on the function parameters
*
* @param files The files that should be coppied
*/
async function copyOptional(files: string[]) {
await Promise.all(
(
await walkDirectory(templateDir)
const directoryContents = await walkDirectory(templateDirectory)
for (const file of directoryContents) {
if (
!file.includes('.optional') &&
!files
.map((induvidualFile) => file.includes(induvidualFile))
.some(Boolean)
)
.filter((f) => f.includes('.optional'))
.filter((f) => files.map((file) => f.includes(file)).some((b) => b))
.map(async (file) => {
const out = join(projectDir, file.replace(templateDir, '')).replace(
'.optional',
''
)
if (!existsSync(out)) {
mkdirSync(dirname(out), { recursive: true })
await copyFile(file, out)
}
})
)
continue
const outLocation = join(
projectDirectory,
file.replace(templateDirectory, '')
).replace('.optional', '')
if (!existsSync(outLocation)) {
mkdirSync(dirname(outLocation), { recursive: true })
await copyFile(file, outLocation)
}
}
}
/**
* Copy all non-optional files from the template directory
*/
async function copyRequired() {
await Promise.all(
(
await walkDirectory(templateDir)
const directoryContents = await walkDirectory(templateDirectory)
for (const file of directoryContents) {
if (file.includes('.optional')) continue
const outLocation = join(
projectDirectory,
file.replace(templateDirectory, '')
)
.filter((f) => !f.includes('.optional'))
.map(async (file) => {
const out = join(projectDir, file.replace(templateDir, ''))
if (!existsSync(out)) {
mkdirSync(dirname(out), { recursive: true })
await copyFile(file, out)
}
})
)
if (!existsSync(outLocation)) {
mkdirSync(dirname(outLocation), { recursive: true })
await copyFile(file, outLocation)
}
}
}

View file

@ -1,9 +1,9 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { existsSync } from 'fs'
import { existsSync } from 'node:fs'
import { log } from '../log'
import { ENGINE_DIR } from '../constants'
import { BIN_NAME, ENGINE_DIR } from '../constants'
import { dispatch, hasConfig } from '../utils'
export const status = async (): Promise<void> => {
@ -12,7 +12,7 @@ export const status = async (): Promise<void> => {
if (!configExists && !engineExists) {
log.info(
"Melon doesn't appear to be setup for this project. You can set it up by running |melon setup-project|"
`Gluon doesn't appear to be setup for this project. You can set it up by running |${BIN_NAME} setup-project|`
)
return
@ -25,7 +25,7 @@ export const status = async (): Promise<void> => {
return
} else {
log.info(
"It appears that melon has been configured, but you haven't run |melon download|"
`It appears that ${BIN_NAME} has been configured, but you haven't run |${BIN_NAME} download|`
)
return

View file

@ -1,8 +1,13 @@
import { stat, writeFile } from 'fs/promises'
import { dirname, join } from 'path'
import { writeFile } from 'node:fs/promises'
import { dirname, join } from 'node:path'
import { create } from 'xmlbuilder2'
import { DIST_DIR } from '../../constants'
import { dynamicConfig, ensureDir, generateHash, getSize } from '../../utils'
import {
dynamicConfig,
ensureDirectory,
generateHash,
getSize,
} from '../../utils'
import {
downloadAddon,
getAddons,
@ -45,6 +50,6 @@ export async function generateAddonUpdateFiles() {
'update.xml'
)
await ensureDir(dirname(path))
await ensureDirectory(dirname(path))
await writeFile(path, root.end({ prettyPrint: true }))
}

View file

@ -1,8 +1,8 @@
import { existsSync } from 'fs'
import { readFile, writeFile } from 'fs/promises'
import { existsSync } from 'node:fs'
import { readFile, writeFile } from 'node:fs/promises'
import { parse } from 'ini'
import { isAppleSilicon } from 'is-apple-silicon'
import { dirname, join } from 'path'
import { dirname, join } from 'node:path'
import { create } from 'xmlbuilder2'
import { bin_name, config } from '../..'
import { DIST_DIR, OBJ_DIR } from '../../constants'
@ -41,7 +41,8 @@ export async function getPlatformConfig() {
if (!existsSync(platformINI))
platformINI = join(OBJ_DIR, 'dist', 'bin', 'platform.ini')
return parse((await readFile(platformINI)).toString())
const iniContents = await readFile(platformINI)
return parse(iniContents.toString())
}
function getReleaseMarName(releaseInfo: ReleaseInfo): string | undefined {
@ -52,12 +53,15 @@ function getReleaseMarName(releaseInfo: ReleaseInfo): string | undefined {
}
switch (process.platform) {
case 'win32':
case 'win32': {
return releaseInfo.x86?.windowsMar
case 'darwin':
}
case 'darwin': {
return releaseInfo.x86?.macosMar
case 'linux':
}
case 'linux': {
return releaseInfo.x86?.linuxMar
}
}
}
@ -84,7 +88,7 @@ async function writeUpdateFileToDisk(
channel: string,
updateObject: {
updates: {
update: Record<string, any>
update: Record<string, string | undefined>
}
}
) {

View file

@ -2,8 +2,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import execa from 'execa'
import { existsSync, mkdirSync, readdirSync } from 'fs'
import { resolve } from 'path'
import { existsSync, mkdirSync, readdirSync } from 'node:fs'
import { resolve } from 'node:path'
import { log } from '../log'
export const BIN_NAME = 'gluon'
@ -63,13 +63,13 @@ export const OBJ_DIR = resolve(ENGINE_DIR, `obj-${CONFIG_GUESS}`)
// TODO: Remove this, it is unused
export const FTL_STRING_LINE_REGEX =
/(([a-zA-Z0-9-]*|\.[a-z-]*) =(.*|\.)|\[[a-zA-Z0-9]*\].*(\n\s?\s?})?|\*\[[a-zA-Z0-9]*\] .*(\n\s?\s?})?)/gm
/(([\dA-Za-z-]*|\.[a-z-]*) =(.*|\.)|\[[\dA-Za-z]*].*(\n\s?\s?})?|\*\[[\dA-Za-z]*] .*(\n\s?\s?})?)/gm
// =================
// Windows constants
// =================
export let BASH_PATH: string | null = null
export let BASH_PATH: string | undefined
// All windows specific code should be located inside of this if statement
if (process.platform == 'win32') {

View file

@ -3,14 +3,7 @@ import { config } from '..'
const otherBuildModes = `# You can change to other build modes by running:
# $ gluon set buildMode [dev|debug|release]`
const platformOptimize =
process.platform == 'darwin'
? 'ac_add_options --enable-optimize="-O3 -march=nehalem -mtune=haswell -w"'
: process.platform == 'linux'
? 'ac_add_options --enable-optimize="-O3 -march=haswell -mtune=haswell -w"'
: process.platform == 'win32'
? 'ac_add_options --enable-optimize="-O2 -Qvec -w -clang:-ftree-vectorize -clang:-msse3 -clang:-mssse3 -clang:-msse4.1 -clang:-mtune=haswell"'
: `# Unknown platform ${process.platform}`
const platformOptimize = getPlatformOptimiseFlags()
export const internalMozconfg = (
brand: string,
@ -20,24 +13,27 @@ export const internalMozconfg = (
// Get the specific build options for the current build mode
switch (buildMode) {
case 'dev':
case 'dev': {
buildOptions = `# Development build settings
${otherBuildModes}
ac_add_options --disable-debug`
break
case 'debug':
}
case 'debug': {
buildOptions = `# Debug build settings
${otherBuildModes}
ac_add_options --enable-debug
ac_add_options --disable-optimize`
break
}
case 'release':
case 'release': {
buildOptions = `# Release build settings
ac_add_options --disable-debug
ac_add_options --enable-optimize
${platformOptimize} # Taken from waterfox`
break
}
}
return `
@ -61,3 +57,24 @@ export MOZ_APPUPDATE_HOST=${
}
`
}
function getPlatformOptimiseFlags(): string {
let optimiseFlags = `# Unknown platform ${process.platform}`
switch (process.platform) {
case 'linux': {
optimiseFlags = `ac_add_options --enable-optimize="-O3 -march=haswell -mtune=haswell -w"`
break
}
case 'darwin': {
optimiseFlags = `ac_add_options --enable-optimize="-O3 -march=nehalem -mtune=haswell -w"`
break
}
case 'win32': {
optimiseFlags = `ac_add_options --enable-optimize="-O2 -Qvec -w -clang:-ftree-vectorize -clang:-msse3 -clang:-mssse3 -clang:-msse4.1 -clang:-mtune=haswell"`
break
}
}
return optimiseFlags
}

View file

@ -4,19 +4,19 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import commander, { Command } from 'commander'
import { existsSync, readFileSync } from 'fs'
import { resolve } from 'path'
import { existsSync, readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { errorHandler, config as configInited, versionFormatter } from './utils'
import { commands } from './cmds'
import { BIN_NAME, ENGINE_DIR } from './constants'
import { updateCheck } from './middleware/update-check'
import { registerCommand } from './middleware/registerCommand'
import { registerCommand } from './middleware/register-command'
import { log } from './log'
// We have to use a dynamic require here, otherwise the typescript compiler
// mucks up the directory structure
// eslint-disable-next-line @typescript-eslint/no-var-requires
// eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module
const { version: gluonVersion } = require('../package.json')
export const config = configInited
@ -76,14 +76,13 @@ async function middleware(command: commander.Command) {
registerCommand(command.name())
}
commands.forEach((command) => {
if (command.flags) {
if (
command.flags.platforms &&
!command.flags.platforms.includes(process.platform)
) {
return
}
for (const command of commands) {
if (
command.flags &&
command.flags.platforms &&
!command.flags.platforms.includes(process.platform)
) {
continue
}
let buildCommand = program
@ -92,11 +91,11 @@ commands.forEach((command) => {
.aliases(command?.aliases || [])
// Register all of the required options
command?.options?.forEach((opt) => {
for (const opt of command?.options || []) {
buildCommand = buildCommand.option(opt.arg, opt.description)
})
}
buildCommand = buildCommand.action(async (...args) => {
buildCommand = buildCommand.action(async (...arguments_) => {
// Start loading the controller in the background whilst middleware is
// executing
const controller = command.requestController()
@ -107,12 +106,12 @@ commands.forEach((command) => {
// Finish loading the controller and execute it
// eslint-disable-next-line @typescript-eslint/no-extra-semi
;(await controller)(...args)
;(await controller)(...arguments_)
})
})
}
process
.on('uncaughtException', errorHandler)
.on('unhandledException', (err) => errorHandler(err, true))
.on('unhandledException', (error) => errorHandler(error, true))
program.parse(process.argv)

View file

@ -4,6 +4,9 @@
import chalk from 'chalk'
import prompts from 'prompts'
const formatToDoubleDigit = (r: number) =>
r.toString().length == 1 ? `0${r}` : r
class Log {
private startTime: number
@ -26,15 +29,15 @@ class Log {
const mins = Math.floor((elapsedTime / (60 * 1000)) % 60)
const hours = Math.floor((elapsedTime / (60 * 60 * 1000)) % 24)
const format = (r: number) => (r.toString().length == 1 ? `0${r}` : r)
return `${format(hours)}:${format(mins)}:${format(secs)}`
return `${formatToDoubleDigit(hours)}:${formatToDoubleDigit(
mins
)}:${formatToDoubleDigit(secs)}`
}
set isDebug(val: boolean) {
log.debug(`Logger debug mode has been ${val ? 'enabled' : 'disabled'}`)
this._isDebug = val
log.debug(`Logger debug mode has been ${val ? 'enabled' : 'disabled'}`)
set isDebug(value: boolean) {
log.debug(`Logger debug mode has been ${value ? 'enabled' : 'disabled'}`)
this._isDebug = value
log.debug(`Logger debug mode has been ${value ? 'enabled' : 'disabled'}`)
}
get isDebug() {
@ -46,8 +49,8 @@ class Log {
*
* @param args The information you want to provide to the user
*/
debug(...args: unknown[]): void {
if (this.isDebug) console.debug(...args)
debug(...arguments_: unknown[]): void {
if (this.isDebug) console.debug(...arguments_)
}
/**
@ -57,8 +60,8 @@ class Log {
*
* @param args The information you want to provide to the user
*/
info(...args: unknown[]): void {
console.info(chalk.blueBright.bold(this.getDiff()), ...args)
info(...arguments_: unknown[]): void {
console.info(chalk.blueBright.bold(this.getDiff()), ...arguments_)
}
/**
@ -68,8 +71,8 @@ class Log {
*
* @param args The information you want to provide to the user
*/
warning(...args: unknown[]): void {
console.warn(chalk.yellowBright.bold(' WARNING'), ...args)
warning(...arguments_: unknown[]): void {
console.warn(chalk.yellowBright.bold(' WARNING'), ...arguments_)
}
/**
@ -78,8 +81,8 @@ class Log {
*
* @param args The information you want to provide to the user
*/
async hardWarning(...args: unknown[]): Promise<void> {
console.info('', chalk.bgRed.bold('WARNING'), ...args)
async hardWarning(...arguments_: unknown[]): Promise<void> {
console.info('', chalk.bgRed.bold('WARNING'), ...arguments_)
const { answer } = await prompts({
type: 'confirm',
@ -95,9 +98,12 @@ class Log {
*
* @param args The information you want to provide to the user
*/
success(...args: unknown[]): void {
success(...arguments_: unknown[]): void {
console.log()
console.log(`\n${chalk.greenBright.bold('SUCCESS')}`, args.join('\n\t'))
console.log(
`\n${chalk.greenBright.bold('SUCCESS')}`,
arguments_.join('\n\t')
)
}
/**
@ -105,11 +111,11 @@ class Log {
*
* @param args The error you want to throw or a type that you want to convert to an error
*/
error(...args: (Error | unknown)[]): never {
throw args[0] instanceof Error
? args[0]
error(...arguments_: (Error | unknown)[]): never {
throw arguments_[0] instanceof Error
? arguments_[0]
: new Error(
...args.map((a) =>
...arguments_.map((a) =>
typeof a !== 'undefined' ? (a as object).toString() : a
)
)

View file

@ -5,8 +5,8 @@
* Responsible for checking if all new patches have been applied
*/
import { existsSync, readFileSync, writeFileSync } from 'fs'
import { resolve } from 'path'
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { log } from '../log'
import { MELON_DIR, SRC_DIR } from '../constants'
import { walkDirectory } from '../utils'
@ -14,14 +14,12 @@ import { walkDirectory } from '../utils'
export const patchCountFile = resolve(MELON_DIR, 'patchCount')
export const patchCheck = async (): Promise<void> => {
const fileList = (await walkDirectory(resolve(SRC_DIR))).filter((file) =>
file.endsWith('.patch')
)
const directoryCotnents = await walkDirectory(resolve(SRC_DIR))
const fileList = directoryCotnents.filter((file) => file.endsWith('.patch'))
const patchCount = fileList.length
if (!existsSync(patchCountFile)) {
writeFileSync(patchCountFile, '0')
}
if (!existsSync(patchCountFile)) writeFileSync(patchCountFile, '0')
const recordedPatchCount = Number(readFileSync(patchCountFile).toString())

View file

@ -1,8 +1,8 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { writeFileSync } from 'fs'
import { resolve } from 'path'
import { writeFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { MELON_DIR } from '../constants'
/**

View file

@ -15,9 +15,9 @@ export const updateCheck = async (): Promise<void> => {
log.warning(
`Latest version of Firefox (${version}) does not match frozen version (${firefoxVersion}).`
)
} catch (e) {
} catch (error) {
log.warning(`Failed to check for updates.`)
log.askForReport()
log.error(e)
log.error(error)
}
}

2
src/types.d.ts vendored
View file

@ -11,7 +11,7 @@ export interface Cmd {
* writing, is getting a touch long
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
requestController: () => Promise<(...args: any) => void>
requestController: () => Promise<(...arguments_: any) => void>
options?: CmdOption[]
aliases?: string[]

View file

View file

@ -1,8 +1,8 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { readFile } from 'fs/promises'
import { createHash } from 'crypto'
import { readFile } from 'node:fs/promises'
import { createHash } from 'node:crypto'
import { readItem, writeItem } from './store'
/**

View file

@ -21,9 +21,9 @@
// Adapted from the `command-exists` node module
// https://github.com/mathisonian/command-exists
import { execSync } from 'child_process'
import { accessSync, constants } from 'fs'
import path from 'path'
import { execSync } from 'node:child_process'
import { accessSync, constants } from 'node:fs'
import path from 'node:path'
const onWindows = process.platform == 'win32'
@ -31,7 +31,7 @@ const fileNotExistsSync = (commandName: string): boolean => {
try {
accessSync(commandName, constants.F_OK)
return false
} catch (e) {
} catch {
return true
}
}
@ -40,7 +40,7 @@ const localExecutableSync = (commandName: string): boolean => {
try {
accessSync(commandName, constants.F_OK | constants.X_OK)
return true
} catch (e) {
} catch {
return false
}
}
@ -60,7 +60,7 @@ const commandExistsUnixSync = function (
'; exit 0; }'
)
return !!stdout
} catch (error) {
} catch {
return false
}
}
@ -73,7 +73,7 @@ const commandExistsWindowsSync = function (
): boolean {
// Regex from Julio from: https://stackoverflow.com/questions/51494579/regex-windows-path-validator
if (
!/^(?!(?:.*\s|.*\.|\W+)$)(?:[a-zA-Z]:)?(?:(?:[^<>:"|?*\n])+(?:\/\/|\/|\\\\|\\)?)+$/m.test(
!/^(?!(?:.*\s|.*\.|\W+)$)(?:[A-Za-z]:)?(?:[^\n"*:<>?|]+(?:\/\/|\/|\\\\|\\)?)+$/m.test(
commandName
)
) {
@ -82,7 +82,7 @@ const commandExistsWindowsSync = function (
try {
const stdout = execSync('where ' + cleanedCommandName, { stdio: [] })
return !!stdout
} catch (error) {
} catch {
return false
}
}
@ -91,7 +91,7 @@ function cleanInput(toBeCleaned: string): string {
// Windows has a different cleaning process to Unix, so we should go through
// that process first
if (onWindows) {
const isPathName = /[\\]/.test(toBeCleaned)
const isPathName = /\\/.test(toBeCleaned)
if (isPathName) {
const dirname = '"' + path.dirname(toBeCleaned) + '"'
const basename = '"' + path.basename(toBeCleaned) + '"'
@ -102,7 +102,7 @@ function cleanInput(toBeCleaned: string): string {
}
// Otherwise go through the unix cleaning process
if (/[^A-Za-z0-9_\\/:=-]/.test(toBeCleaned)) {
if (/[^\w/:=\\-]/.test(toBeCleaned)) {
toBeCleaned = "'" + toBeCleaned.replace(/'/g, "'\\''") + "'"
toBeCleaned = toBeCleaned
.replace(/^(?:'')+/g, '') // unduplicate single-quote at the beginning
@ -114,9 +114,5 @@ function cleanInput(toBeCleaned: string): string {
export function commandExistsSync(commandName: string): boolean {
const cleanedCommandName = cleanInput(commandName)
if (onWindows) {
return commandExistsWindowsSync(commandName, cleanedCommandName)
} else {
return commandExistsUnixSync(commandName, cleanedCommandName)
}
return onWindows ? commandExistsWindowsSync(commandName, cleanedCommandName) : commandExistsUnixSync(commandName, cleanedCommandName);
}

View file

@ -1,7 +1,7 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'fs'
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'
import {
configPath,
defaultConfig,

View file

@ -5,21 +5,21 @@
* Responsible for loading, parsing and checking the config file for melon
*/
import { existsSync, readFileSync, writeFileSync } from 'fs'
import { join } from 'path'
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'
import { BIN_NAME } from '../constants'
import { log } from '../log'
export const projectDir = process.cwd()
export const configPath = join(projectDir, 'gluon.json')
export const projectDirectory = process.cwd()
export const configPath = join(projectDirectory, 'gluon.json')
let hasWarnedAboutConfig = false
export enum SupportedProducts {
Firefox = 'firefox',
FirefoxESR = 'firefox-esr',
FirefoxESRNext = 'firefox-esr-next',
FirefoxDev = 'firefox-dev',
FirefoxDevelopment = 'firefox-dev',
FirefoxBeta = 'firefox-beta',
FirefoxNightly = 'firefox-nightly',
}
@ -27,8 +27,7 @@ export enum SupportedProducts {
export const validProducts = [
SupportedProducts.Firefox,
SupportedProducts.FirefoxESR,
SupportedProducts.FirefoxESRNext,
SupportedProducts.FirefoxDev,
SupportedProducts.FirefoxDevelopment,
SupportedProducts.FirefoxBeta,
SupportedProducts.FirefoxNightly,
]
@ -214,10 +213,10 @@ export function getConfig(): Config {
try {
// Try to parse the contents of the file. May not be valid JSON
fileParsed = JSON.parse(fileContents)
} catch (e) {
} catch (error) {
// Report the error to the user
log.error(`Error parsing melon config file located at ${configPath}`)
log.error(e)
log.error(`Error parsing ${BIN_NAME} config file located at ${configPath}`)
log.error(error)
process.exit(1)
}
@ -293,7 +292,7 @@ export function getConfig(): Config {
}
export function saveConfig() {
writeFileSync(configPath, JSON.stringify(config, null, 2))
writeFileSync(configPath, JSON.stringify(config, undefined, 2))
}
export const config = getConfig()

View file

@ -36,26 +36,29 @@ export const configDispatch = (
if (config?.shell) {
switch (config.shell) {
// Don't change anything if we are using the default shell
case 'default':
case 'default': {
break
}
case 'unix':
case 'unix': {
// Bash path provides a unix shell on windows
shell = BASH_PATH || false
break
}
default:
default: {
log.error(`dispatch() does not understand the shell '${shell}'`)
break
}
}
}
const handle = (data: string | Error, killOnError?: boolean) => {
const d = data.toString()
const dataAsString = data.toString()
d.split('\n').forEach((line: string) => {
if (line.length !== 0) logger(removeTimestamp(line))
})
for (const line of dataAsString.split('\n')) {
if (line.length > 0) logger(removeTimestamp(line))
}
if (killOnError) {
log.error('Command failed. See error above.')
@ -67,7 +70,7 @@ export const configDispatch = (
cwd: config?.cwd || process.cwd(),
shell: shell,
env: {
...(config?.env || {}),
...config?.env,
...process.env,
},
})
@ -89,13 +92,13 @@ export const configDispatch = (
*/
export const dispatch = (
cmd: string,
args?: string[],
arguments_?: string[],
cwd?: string,
killOnError?: boolean,
logger = (data: string) => log.info(data)
): Promise<boolean> => {
return configDispatch(cmd, {
args: args,
args: arguments_,
cwd: cwd,
killOnError: killOnError,
logger: logger,

View file

@ -1,11 +1,12 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { createWriteStream } from 'fs'
import { createWriteStream } from 'node:fs'
import axios from 'axios'
import cliProgress from 'cli-progress'
import { Duplex } from 'stream'
import { Duplex } from 'node:stream'
import { log } from '../log'
export async function downloadFileToLocation(
url: string,
@ -43,7 +44,12 @@ export async function downloadFileToLocation(
receivedBytes += chunk.length
})
data.pipe(writer)
data.on('error', (err: unknown) => reject(err))
data.on('error', (error: unknown) => {
log.warning(
`An error occured whilst downloading ${url}. It might be ignored`
)
reject(error)
})
const progressInterval = setInterval(
() => progressBar.update(receivedBytes),

View file

@ -2,7 +2,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import * as dynamicConfig from './dynamicConfig'
import * as dynamicConfig from './dynamic-config'
import { readItem, removeItem } from './store'
describe('set', () => {

View file

@ -2,12 +2,12 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import chalk from 'chalk'
import { readFileSync } from 'fs'
import { resolve } from 'path'
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { MELON_DIR } from '../constants'
import { log } from '../log'
export const errorHandler = (err: Error, isUnhandledRej: boolean): void => {
export const errorHandler = (error: Error, isUnhandledRej: boolean): never => {
let cc = readFileSync(resolve(MELON_DIR, 'command')).toString()
cc = cc.replace(/(\r\n|\n|\r)/gm, '')
@ -21,13 +21,13 @@ export const errorHandler = (err: Error, isUnhandledRej: boolean): void => {
console.log(
`\n\t`,
isUnhandledRej
? err.toString().replace(/\n/g, '\n\t ')
: err.message.replace(/\n/g, '\n\t ')
? error.toString().replace(/\n/g, '\n\t ')
: error.message.replace(/\n/g, '\n\t ')
)
if (err.stack || isUnhandledRej) {
const stack: string[] | undefined = err.stack?.split('\n')
if (error.stack || isUnhandledRej) {
const stack: string[] | undefined = error.stack?.split('\n')
if (!stack) return
if (!stack) process.exit(1)
stack.shift()
stack.shift()

View file

@ -8,9 +8,9 @@ import {
openSync,
rmSync,
writeSync,
} from 'fs'
import { mkdir, readdir, stat, symlink } from 'fs/promises'
import { join, isAbsolute, dirname, relative } from 'path'
} from 'node:fs'
import { mkdir, readdir, stat } from 'node:fs/promises'
import { join, isAbsolute } from 'node:path'
import { log } from '../log'
@ -24,19 +24,19 @@ import { log } from '../log'
export const windowsPathToUnix = (path: string): string =>
process.platform == 'win32' ? path.replace(/\\/g, '/') : path
export async function walkDirectory(dirName: string): Promise<string[]> {
export async function walkDirectory(directory: string): Promise<string[]> {
const output = []
if (!isAbsolute(dirName)) {
if (!isAbsolute(directory)) {
log.askForReport()
log.error('Please provide an absolute input to walkDirectory')
}
try {
const directoryContents = await readdir(dirName)
const directoryContents = await readdir(directory)
for (const file of directoryContents) {
const fullPath = join(dirName, file)
const fullPath = join(directory, file)
const fStat = await stat(fullPath)
if (fStat.isDirectory()) {
@ -47,9 +47,9 @@ export async function walkDirectory(dirName: string): Promise<string[]> {
output.push(fullPath)
}
}
} catch (e) {
} catch (error) {
log.askForReport()
log.error(e)
log.error(error)
}
return output
@ -57,21 +57,21 @@ export async function walkDirectory(dirName: string): Promise<string[]> {
export type TreeType = { [property: string]: string[] | TreeType }
export async function walkDirectoryTree(dirName: string): Promise<TreeType> {
export async function walkDirectoryTree(directory: string): Promise<TreeType> {
const output: TreeType = {}
if (!isAbsolute(dirName)) {
if (!isAbsolute(directory)) {
log.askForReport()
log.error('Please provide an absolute input to walkDirectory')
}
try {
const directoryContents = await readdir(dirName)
const directoryContents = await readdir(directory)
const currentOut = []
for (const file of directoryContents) {
const fullPath = join(dirName, file)
const fullPath = join(directory, file)
const fStat = await stat(fullPath)
if (fStat.isDirectory()) {
@ -82,26 +82,26 @@ export async function walkDirectoryTree(dirName: string): Promise<TreeType> {
}
output['.'] = currentOut
} catch (e) {
} catch (error) {
log.askForReport()
log.error(e)
log.error(error)
}
return output
}
export async function ensureDir(dirName: string): Promise<void> {
if (!existsSync(dirName)) {
await mkdirp(dirName)
export async function ensureDirectory(directory: string): Promise<void> {
if (!existsSync(directory)) {
await mkdirp(directory)
}
}
export function mkdirp(dirName: string): Promise<string | undefined> {
return mkdir(dirName, { recursive: true })
export function mkdirp(directory: string): Promise<string | undefined> {
return mkdir(directory, { recursive: true })
}
export function mkdirpSync(dirName: string): string | undefined {
return mkdirSync(dirName, { recursive: true })
export function mkdirpSync(directory: string): string | undefined {
return mkdirSync(directory, { recursive: true })
}
export function appendToFileSync(fileName: string, content: string): void {
@ -110,58 +110,6 @@ export function appendToFileSync(fileName: string, content: string): void {
closeSync(file)
}
export async function createSymlink(
srcPath: string,
destPath: string,
type?: string
): Promise<void> {
if (existsSync(destPath)) return
const { toDest: src } = symlinkPaths(srcPath, destPath)
const dir = dirname(destPath)
const exists = existsSync(dir)
if (exists) return await symlink(src, destPath, type)
await mkdirp(dir)
return await symlink(src, destPath, type)
}
/**
* Adapted from fs-extra
* @param srcPath
* @param destPath
* @returns
*/
export function symlinkPaths(
srcPath: string,
destPath: string
): { toCwd: string; toDest: string } {
if (isAbsolute(srcPath)) {
if (!existsSync(srcPath)) throw new Error('absolute srcpath does not exist')
return {
toCwd: srcPath,
toDest: srcPath,
}
} else {
const dstdir = dirname(destPath)
const relativeToDst = join(dstdir, srcPath)
if (existsSync(relativeToDst))
return {
toCwd: relativeToDst,
toDest: srcPath,
}
else {
if (!existsSync(srcPath))
throw new Error('relative srcpath does not exist')
return {
toCwd: srcPath,
toDest: relative(dstdir, srcPath),
}
}
}
}
export function filesExist(files: string[]): boolean {
return files.every((file) => existsSync(file))
}
@ -175,5 +123,6 @@ export function ensureEmpty(path: string) {
}
export async function getSize(path: string): Promise<number> {
return (await stat(path)).size
const fileInfo = await stat(path)
return fileInfo.size
}

View file

@ -1,14 +1,14 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
export * from './commandExists'
export * from './changeTracking'
export * from './command-exists'
export * from './change-tracking'
export * from './delay'
export * from './dispatch'
export * from './error-handler'
export * from './version'
export * from './config'
export * from './stringTemplate'
export * from './string-template'
export * from './fs'
export * from './versionFormatter'
export * as dynamicConfig from './dynamicConfig'
export * from './version-formatter'
export * as dynamicConfig from './dynamic-config'

View file

@ -1,27 +1,27 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'fs'
import { join } from 'path'
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'
import { equip, None, OptionEquipped } from 'rustic'
import { MELON_DIR } from '../constants'
export const readItem = <T>(key: string): OptionEquipped<T> => {
const dir = join(MELON_DIR, `${key}.json`)
const fileLocation = join(MELON_DIR, `${key}.json`)
if (!existsSync(dir)) {
if (!existsSync(fileLocation)) {
return equip<T>(None)
}
const data = readFileSync(dir).toString()
const data = readFileSync(fileLocation).toString()
return equip(JSON.parse(data))
}
export const writeItem = <T>(key: string, data: T) => {
const dir = join(MELON_DIR, `${key}.json`)
writeFileSync(dir, JSON.stringify(data, null, 2))
const fileLocation = join(MELON_DIR, `${key}.json`)
writeFileSync(fileLocation, JSON.stringify(data, undefined, 2))
}
export const removeItem = (key: string) => {

View file

@ -8,15 +8,15 @@ export function stringTemplate(
template: string,
variables: { [key: string]: string | number }
): string {
let temp = template
let temporary = template
for (const variable in variables) {
// Replace only replaces the first instance of a string. We want to
// replace all instances
while (temp.includes(`\${${variable}}`)) {
temp = temp.replace(`\${${variable}}`, variables[variable].toString())
while (temporary.includes(`\${${variable}}`)) {
temporary = temporary.replace(`\${${variable}}`, variables[variable].toString())
}
}
return temp
return temporary
}

122
src/utils/task-list.ts Normal file
View file

@ -0,0 +1,122 @@
import kleur from 'kleur'
export type LoggingMode = 'silent' | 'normal'
export type LoggingErrorMode = 'inline' | 'throw'
export interface Task {
name: string
skip?: () => boolean | Promise<boolean>
long?: boolean
task: (
log: (message: string) => void
) => void | Promise<void> | TaskList | Promise<TaskList>
}
export class TaskList {
tasks: Task[]
loggingStyle: LoggingMode = 'normal'
loggingIndentation = ''
loggingOnError: LoggingErrorMode = 'throw'
error?: Error
constructor(tasks: Task[]) {
this.tasks = tasks
}
style(style: LoggingMode) {
this.loggingStyle = style
return this
}
indent(indentation: string) {
this.loggingIndentation = indentation
return this
}
onError(mode: LoggingErrorMode) {
this.loggingOnError = mode
return this
}
private log(
type: 'start' | 'finish' | 'fail' | 'skip' | 'info',
name: string
) {
if (this.loggingStyle == 'silent') return
let prefix = this.loggingIndentation
const prefixTemplate = `[${type.toUpperCase()}]`
switch (type) {
case 'start': {
prefix += kleur.bold().gray(prefixTemplate)
break
}
case 'finish': {
prefix += kleur.bold().green(prefixTemplate)
break
}
case 'fail': {
prefix += kleur.bold().red(prefixTemplate)
break
}
case 'skip': {
prefix += kleur.bold().yellow(prefixTemplate)
break
}
case 'info': {
prefix += ' '
prefix += kleur.bold().cyan(prefixTemplate)
break
}
}
console.log(`${prefix} ${name}`)
}
async run() {
for (const task of this.tasks) {
if (task.skip && (await task.skip())) {
this.log('skip', task.name)
continue
}
if (task.long) {
this.log('start', task.name)
}
try {
const result = await task.task((message: string) =>
this.log('info', message)
)
if (result instanceof TaskList) {
// We want to provide a start point if none exists already
if (!task.long) {
this.log('start', task.name)
}
await result.indent(this.loggingIndentation + ' ').run()
}
} catch (error) {
if (this.loggingOnError == 'throw') {
this.log('fail', task.name)
throw error
}
if (this.loggingOnError == 'inline') {
this.log('fail', `${task.name}: ${error}`)
}
this.error = error as Error
}
this.log('finish', task.name)
}
if (this.error) {
throw this.error
}
}
}

View file

@ -7,8 +7,8 @@ export const versionFormatter = (
options: ({ name: string; value: string } | null | string)[]
): string => {
const spacesValue = Math.max(
...options.map((arg) =>
typeof arg === 'string' ? 0 : arg?.value?.length || 0
...options.map((argument) =>
typeof argument === 'string' ? 0 : argument?.value?.length || 0
)
)

15
src/utils/version.test.ts Normal file
View file

@ -0,0 +1,15 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import { validProducts } from './config'
import { getLatestFF } from './version'
const firefoxVersions = validProducts
describe('getLatestFF', () => {
for (const firefoxVersion of firefoxVersions) {
it(`returns the latest ${firefoxVersion} version`, async () =>
expect(await getLatestFF(firefoxVersion)).toBeTruthy())
}
})

View file

@ -2,23 +2,30 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import axios from 'axios'
import { log } from '../log'
import { SupportedProducts } from './config'
const firefoxTargets = JSON.parse(`{
"${SupportedProducts.Firefox}": "LATEST_FIREFOX_VERSION",
"${SupportedProducts.FirefoxBeta}": "LATEST_FIREFOX_DEVEL_VERSION",
"${SupportedProducts.FirefoxDev}": "FIREFOX_DEVEDITION",
"${SupportedProducts.FirefoxDevelopment}": "FIREFOX_DEVEDITION",
"${SupportedProducts.FirefoxESR}": "FIREFOX_ESR",
"${SupportedProducts.FirefoxESRNext}": "FIREFOX_ESR_NEXT",
"${SupportedProducts.FirefoxNightly}": "FIREFOX_NIGHTLY"
}`)
export const getLatestFF = async (
product: SupportedProducts = SupportedProducts.Firefox
): Promise<string> => {
const { data } = await axios.get(
'https://product-details.mozilla.org/1.0/firefox_versions.json'
)
try {
const { data } = await axios.get(
'https://product-details.mozilla.org/1.0/firefox_versions.json'
)
return data[firefoxTargets[product]]
return data[firefoxTargets[product]]
} catch (error) {
log.warning('Failed to get latest firefox version with error:')
log.error(error)
return ''
}
}

View file

@ -1 +0,0 @@
# Melon build tool

498
yarn.lock
View file

@ -127,6 +127,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076"
integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==
"@babel/helper-validator-identifier@^7.19.1":
version "7.19.1"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
"@babel/helper-validator-option@^7.18.6":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
@ -963,13 +968,6 @@
"@resvg/resvg-js-win32-ia32-msvc" "1.4.0"
"@resvg/resvg-js-win32-x64-msvc" "1.4.0"
"@samverschueren/stream-to-observable@^0.3.0":
version "0.3.1"
resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz#a21117b19ee9be70c379ec1877537ef2e1c63301"
integrity sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==
dependencies:
any-observable "^0.3.0"
"@sinonjs/commons@^1.7.0":
version "1.8.3"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
@ -1102,9 +1100,9 @@
integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
"@types/node@*":
version "18.6.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.1.tgz#828e4785ccca13f44e2fb6852ae0ef11e3e20ba5"
integrity sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg==
version "18.6.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.2.tgz#ffc5f0f099d27887c8d9067b54e55090fcd54126"
integrity sha512-KcfkBq9H4PI6Vpu5B/KoPeuVDAbmi+2mDBqGPGUgoL7yXQtcWGu2vJWmmRkneWK3Rh0nIAX192Aa87AqKHYChQ==
"@types/node@16.9.1":
version "16.9.1"
@ -1121,6 +1119,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
"@types/normalize-package-data@^2.4.0":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
"@types/picomatch@^2.3.0":
version "2.3.0"
resolved "https://registry.yarnpkg.com/@types/picomatch/-/picomatch-2.3.0.tgz#75db5e75a713c5a83d5b76780c3da84a82806003"
@ -1305,11 +1308,6 @@ ajv@^6.10.0, ajv@^6.12.4:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ansi-escapes@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
ansi-escapes@^4.2.1:
version "4.3.2"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
@ -1317,26 +1315,11 @@ ansi-escapes@^4.2.1:
dependencies:
type-fest "^0.21.3"
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==
ansi-regex@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1"
integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@ -1361,11 +1344,6 @@ any-base@^1.1.0:
resolved "https://registry.yarnpkg.com/any-base/-/any-base-1.1.0.tgz#ae101a62bc08a597b4c9ab5b7089d456630549fe"
integrity sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==
any-observable@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b"
integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==
anymatch@^3.0.3:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
@ -1557,6 +1535,11 @@ buffer@^5.2.0, buffer@^5.5.0:
base64-js "^1.3.1"
ieee754 "^1.1.13"
builtin-modules@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==
callsites@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
@ -1573,22 +1556,11 @@ camelcase@^6.2.0:
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001370:
version "1.0.30001370"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001370.tgz#0a30d4f20d38b9e108cc5ae7cc62df9fe66cd5ba"
integrity sha512-3PDmaP56wz/qz7G508xzjx8C+MC2qEm4SYhSEzC9IBROo+dGXFWRuaXkWti0A9tuI00g+toiriVqxtWMgl350g==
version "1.0.30001373"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001373.tgz#2dc3bc3bfcb5d5a929bec11300883040d7b4b4be"
integrity sha512-pJYArGHrPp3TUqQzFYRmP/lwJlj8RCbVe3Gd3eJQkAV8SAC6b19XS9BjMvRdvaS8RMkaTN8ZhoHP6S1y8zzwEQ==
chalk@^1.0.0, chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==
dependencies:
ansi-styles "^2.2.1"
escape-string-regexp "^1.0.2"
has-ansi "^2.0.0"
strip-ansi "^3.0.0"
supports-color "^2.0.0"
chalk@^2.0.0, chalk@^2.4.1:
chalk@^2.0.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@ -1620,17 +1592,22 @@ ci-info@^3.2.0:
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.2.tgz#6d2967ffa407466481c6c90b6e16b3098f080128"
integrity sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==
ci-info@^3.4.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.5.0.tgz#bfac2a29263de4c829d806b1ab478e35091e171f"
integrity sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==
cjs-module-lexer@^1.0.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
cli-cursor@^2.0.0, cli-cursor@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==
clean-regexp@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/clean-regexp/-/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7"
integrity sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==
dependencies:
restore-cursor "^2.0.0"
escape-string-regexp "^1.0.5"
cli-progress@^3.9.1:
version "3.11.2"
@ -1639,14 +1616,6 @@ cli-progress@^3.9.1:
dependencies:
string-width "^4.2.3"
cli-truncate@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574"
integrity sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg==
dependencies:
slice-ansi "0.0.4"
string-width "^1.0.1"
cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
@ -1661,11 +1630,6 @@ co@^4.6.0:
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==
collect-v8-coverage@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
@ -1780,11 +1744,6 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
date-fns@^1.27.2:
version "1.30.1"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
@ -1871,14 +1830,9 @@ domexception@^2.0.1:
webidl-conversions "^5.0.0"
electron-to-chromium@^1.4.202:
version "1.4.202"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.202.tgz#0c2ed733f42b02ec49a955c5badfcc65888c390b"
integrity sha512-JYsK2ex9lmQD27kj19fhXYxzFJ/phLAkLKHv49A5UY6kMRV2xED3qMMLg/voW/+0AR6wMiI+VxlmK9NDtdxlPA==
elegant-spinner@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
integrity sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==
version "1.4.206"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.206.tgz#580ff85b54d7ec0c05f20b1e37ea0becdd7b0ee4"
integrity sha512-h+Fadt1gIaQ06JaIiyqPsBjJ08fV5Q7md+V8bUvQW/9OvXfL2LRICTz2EcnnCP7QzrFTS6/27MRV6Bl9Yn97zA==
emittery@^0.8.1:
version "0.8.1"
@ -1909,7 +1863,7 @@ escalade@^3.1.1:
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
@ -1936,6 +1890,26 @@ escodegen@^2.0.0:
optionalDependencies:
source-map "~0.6.1"
eslint-plugin-unicorn@^44.0.2:
version "44.0.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-44.0.2.tgz#6324a001c0a5e2ac00fb51b30db27d14c6c36ab3"
integrity sha512-GLIDX1wmeEqpGaKcnMcqRvMVsoabeF0Ton0EX4Th5u6Kmf7RM9WBl705AXFEsns56ESkEs0uyelLuUTvz9Tr0w==
dependencies:
"@babel/helper-validator-identifier" "^7.19.1"
ci-info "^3.4.0"
clean-regexp "^1.0.0"
eslint-utils "^3.0.0"
esquery "^1.4.0"
indent-string "^4.0.0"
is-builtin-module "^3.2.0"
lodash "^4.17.21"
pluralize "^8.0.0"
read-pkg-up "^7.0.1"
regexp-tree "^0.1.24"
safe-regex "^2.1.1"
semver "^7.3.7"
strip-indent "^3.0.0"
eslint-scope@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
@ -2133,21 +2107,6 @@ fb-watchman@^2.0.0:
dependencies:
bser "2.1.1"
figures@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
integrity sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==
dependencies:
escape-string-regexp "^1.0.5"
object-assign "^4.1.0"
figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==
dependencies:
escape-string-regexp "^1.0.5"
file-entry-cache@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
@ -2283,7 +2242,7 @@ glob-parent@^6.0.1:
dependencies:
is-glob "^4.0.3"
glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.7:
glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
@ -2315,6 +2274,11 @@ globals@^13.15.0:
dependencies:
type-fest "^0.20.2"
globalyzer@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465"
integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==
globby@^11.1.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
@ -2327,18 +2291,16 @@ globby@^11.1.0:
merge2 "^1.4.1"
slash "^3.0.0"
globrex@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098"
integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==
graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9:
version "4.2.10"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
has-ansi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==
dependencies:
ansi-regex "^2.0.0"
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@ -2356,6 +2318,11 @@ has@^1.0.3:
dependencies:
function-bind "^1.1.1"
hosted-git-info@^2.1.4:
version "2.8.9"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
html-encoding-sniffer@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
@ -2435,10 +2402,10 @@ imurmurhash@^0.1.4:
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
indent-string@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
integrity sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==
indent-string@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
inflight@^1.0.4:
version "1.0.6"
@ -2477,6 +2444,13 @@ is-arrayish@^0.3.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
is-builtin-module@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.0.tgz#bb0310dfe881f144ca83f30100ceb10cf58835e0"
integrity sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==
dependencies:
builtin-modules "^3.3.0"
is-core-module@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69"
@ -2489,18 +2463,6 @@ is-extglob@^2.1.1:
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
is-fullwidth-code-point@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==
dependencies:
number-is-nan "^1.0.0"
is-fullwidth-code-point@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
@ -2528,28 +2490,11 @@ is-number@^7.0.0:
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-observable@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e"
integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==
dependencies:
symbol-observable "^1.1.0"
is-potential-custom-element-name@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
is-promise@^2.1.0:
version "2.2.2"
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==
is-stream@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
@ -3128,6 +3073,11 @@ kleur@^3.0.3:
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
kleur@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780"
integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@ -3154,50 +3104,6 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
listr-silent-renderer@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e"
integrity sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA==
listr-update-renderer@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2"
integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==
dependencies:
chalk "^1.1.3"
cli-truncate "^0.2.1"
elegant-spinner "^1.0.1"
figures "^1.7.0"
indent-string "^3.0.0"
log-symbols "^1.0.2"
log-update "^2.3.0"
strip-ansi "^3.0.1"
listr-verbose-renderer@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db"
integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==
dependencies:
chalk "^2.4.1"
cli-cursor "^2.1.0"
date-fns "^1.27.2"
figures "^2.0.0"
listr@^0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586"
integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==
dependencies:
"@samverschueren/stream-to-observable" "^0.3.0"
is-observable "^1.1.0"
is-promise "^2.1.0"
is-stream "^1.1.0"
listr-silent-renderer "^1.1.1"
listr-update-renderer "^0.5.0"
listr-verbose-renderer "^0.5.0"
p-map "^2.0.0"
rxjs "^6.3.3"
load-bmfont@^1.3.1, load-bmfont@^1.4.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.1.tgz#c0f5f4711a1e2ccff725a7b6078087ccfcddd3e9"
@ -3229,27 +3135,11 @@ lodash.merge@^4.6.2:
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
lodash@^4.7.0:
lodash@^4.17.21, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
integrity sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ==
dependencies:
chalk "^1.0.0"
log-update@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708"
integrity sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==
dependencies:
ansi-escapes "^3.0.0"
cli-cursor "^2.0.0"
wrap-ansi "^3.0.1"
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@ -3311,11 +3201,6 @@ mime@^1.3.4:
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
mimic-fn@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
mimic-fn@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
@ -3333,6 +3218,11 @@ min-document@^2.19.0:
dependencies:
dom-walk "^0.1.0"
min-indent@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
@ -3407,6 +3297,16 @@ node-releases@^2.0.6:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==
normalize-package-data@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
dependencies:
hosted-git-info "^2.1.4"
resolve "^1.10.0"
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
normalize-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
@ -3419,21 +3319,11 @@ npm-run-path@^4.0.1:
dependencies:
path-key "^3.0.0"
number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==
nwsapi@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.1.tgz#10a9f268fbf4c461249ebcfe38e359aa36e2577c"
integrity sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg==
object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
omggif@^1.0.10, omggif@^1.0.9:
version "1.0.10"
resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19"
@ -3446,13 +3336,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
onetime@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==
dependencies:
mimic-fn "^1.0.0"
onetime@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
@ -3498,11 +3381,6 @@ p-locate@^4.1.0:
dependencies:
p-limit "^2.2.0"
p-map@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==
p-try@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
@ -3543,7 +3421,7 @@ parse-headers@^2.0.0:
resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9"
integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==
parse-json@^5.2.0:
parse-json@^5.0.0, parse-json@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
@ -3617,6 +3495,11 @@ pkg-dir@^4.2.0:
dependencies:
find-up "^4.0.0"
pluralize@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
png-to-ico@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/png-to-ico/-/png-to-ico-2.1.4.tgz#0f14674c79e23bbd4367696b5852693edf28dbee"
@ -3724,6 +3607,25 @@ react-is@^17.0.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
read-pkg-up@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==
dependencies:
find-up "^4.1.0"
read-pkg "^5.2.0"
type-fest "^0.8.1"
read-pkg@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc"
integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==
dependencies:
"@types/normalize-package-data" "^2.4.0"
normalize-package-data "^2.5.0"
parse-json "^5.0.0"
type-fest "^0.6.0"
readable-stream@^3.1.1, readable-stream@^3.4.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
@ -3738,6 +3640,11 @@ regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
regexp-tree@^0.1.24, regexp-tree@~0.1.1:
version "0.1.24"
resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.24.tgz#3d6fa238450a4d66e5bc9c4c14bb720e2196829d"
integrity sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==
regexpp@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
@ -3770,7 +3677,7 @@ resolve.exports@^1.1.0:
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9"
integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==
resolve@^1.20.0:
resolve@^1.10.0, resolve@^1.20.0:
version "1.22.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
@ -3779,14 +3686,6 @@ resolve@^1.20.0:
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
restore-cursor@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==
dependencies:
onetime "^2.0.0"
signal-exit "^3.0.2"
reusify@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
@ -3811,7 +3710,7 @@ rustic@^1.2.1:
resolved "https://registry.yarnpkg.com/rustic/-/rustic-1.2.2.tgz#7b853bccbf0daa6e88d27d7e10aa1909c9bab73f"
integrity sha512-aagYrcImcYj3QbaP7nirOw8/q8aULMu0LkKucP9B4WsRbXlXpk195nYAEB+uJzAcgk2pKS+yMzbAJtIoOqwZoQ==
rxjs@^6.3.3, rxjs@^6.5.1:
rxjs@^6.5.1:
version "6.6.7"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
@ -3828,6 +3727,13 @@ safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safe-regex@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-2.1.1.tgz#f7128f00d056e2fe5c11e81a1324dd974aadced2"
integrity sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==
dependencies:
regexp-tree "~0.1.1"
"safer-buffer@>= 2.1.2 < 3":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@ -3845,6 +3751,11 @@ saxes@^5.0.1:
dependencies:
xmlchars "^2.2.0"
"semver@2 || 3 || 4 || 5":
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
semver@7.x, semver@^7.3.2, semver@^7.3.5, semver@^7.3.7:
version "7.3.7"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
@ -3919,11 +3830,6 @@ slash@^3.0.0:
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
slice-ansi@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
integrity sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw==
source-map-support@^0.5.6:
version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
@ -3942,6 +3848,32 @@ source-map@^0.7.3:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656"
integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
spdx-correct@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
dependencies:
spdx-expression-parse "^3.0.0"
spdx-license-ids "^3.0.0"
spdx-exceptions@^2.1.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
spdx-expression-parse@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
dependencies:
spdx-exceptions "^2.1.0"
spdx-license-ids "^3.0.0"
spdx-license-ids@^3.0.0:
version "3.0.12"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779"
integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
@ -3962,23 +3894,6 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
string-width@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==
dependencies:
code-point-at "^1.0.0"
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
dependencies:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
@ -3995,20 +3910,6 @@ string_decoder@^1.1.1:
dependencies:
safe-buffer "~5.2.0"
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==
dependencies:
ansi-regex "^2.0.0"
strip-ansi@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==
dependencies:
ansi-regex "^3.0.0"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
@ -4026,6 +3927,13 @@ strip-final-newline@^2.0.0:
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
strip-indent@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
dependencies:
min-indent "^1.0.0"
strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
@ -4036,11 +3944,6 @@ strip-json-comments@~2.0.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@ -4075,11 +3978,6 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
symbol-observable@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
symbol-tree@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
@ -4138,6 +4036,14 @@ timm@^1.6.1:
resolved "https://registry.yarnpkg.com/timm/-/timm-1.7.1.tgz#96bab60c7d45b5a10a8a4d0f0117c6b7e5aff76f"
integrity sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==
tiny-glob@^0.2.9:
version "0.2.9"
resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2"
integrity sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==
dependencies:
globalyzer "0.1.0"
globrex "^0.1.2"
tinycolor2@^1.4.1:
version "1.4.2"
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803"
@ -4238,6 +4144,16 @@ type-fest@^0.21.3:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
type-fest@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
type-fest@^0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
typedarray-to-buffer@^3.1.5:
version "3.1.5"
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
@ -4301,6 +4217,14 @@ v8-to-istanbul@^8.1.0:
convert-source-map "^1.6.0"
source-map "^0.7.3"
validate-npm-package-license@^3.0.1:
version "3.0.4"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
dependencies:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
w3c-hr-time@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
@ -4365,14 +4289,6 @@ word-wrap@^1.2.3, word-wrap@~1.2.3:
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
wrap-ansi@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba"
integrity sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==
dependencies:
string-width "^2.1.1"
strip-ansi "^4.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"