refactor: move to Typescript #146
13 changed files with 683 additions and 408 deletions
|
@ -1,6 +1,13 @@
|
|||
module.exports = {
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint"],
|
||||
extends: [
|
||||
"@tophat/eslint-config/base",
|
||||
"@tophat/eslint-config/jest",
|
||||
]
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
settings: {
|
||||
'import/resolver': { node: { extensions: ['.ts'] }}
|
||||
}
|
||||
}
|
||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -102,3 +102,5 @@ dist
|
|||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
*.sw[a-z]
|
||||
|
|
3
.prettierrc
Normal file
3
.prettierrc
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"semi": false
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"comments": false,
|
||||
"ignore": ["**/*.test.js"],
|
||||
"presets": [["@babel/preset-env", { "targets": { "node": 10 } }]]
|
||||
"presets": ["@babel/preset-typescript", ["@babel/preset-env", { "targets": { "node": 10 } }]]
|
||||
}
|
||||
|
|
18
package.json
18
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "packwatch",
|
||||
"version": "0.0.0",
|
||||
"main": "dist/index.js",
|
||||
"main": "dist/cli.js",
|
||||
"description": "📦👀 Keep an eye on your packages' footprint",
|
||||
"keywords": [
|
||||
"npm",
|
||||
|
@ -19,9 +19,9 @@
|
|||
"author": "Marc Cataford <c.marcandre@gmail.com>",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"dist/**/*.js"
|
||||
"dist/*.ts"
|
||||
],
|
||||
"bin": "./dist/index.js",
|
||||
"bin": "./dist/cli.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mcataford/packwatch.git"
|
||||
|
@ -32,8 +32,8 @@
|
|||
],
|
||||
"scripts": {
|
||||
"prebuild": "rimraf dist",
|
||||
"build": "babel src -d dist",
|
||||
"lint": "eslint src *.js",
|
||||
"build": "babel src/index.ts src/cli.ts -d dist --extensions .ts",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"lint:fix": "yarn lint --fix",
|
||||
"test": "jest src",
|
||||
"test:watch": "yarn test --watchAll",
|
||||
|
@ -43,7 +43,12 @@
|
|||
"@babel/cli": "^7.8.4",
|
||||
"@babel/core": "^7.8.6",
|
||||
"@babel/preset-env": "^7.8.7",
|
||||
"@babel/preset-typescript": "^7.12.7",
|
||||
"@tophat/eslint-config": "^0.7.0",
|
||||
"@types/jest": "^26.0.19",
|
||||
"@types/node": "^14.14.13",
|
||||
"@typescript-eslint/eslint-plugin": "^4.9.1",
|
||||
"@typescript-eslint/parser": "^4.9.1",
|
||||
"eslint": "^7.0.0",
|
||||
"eslint-config-prettier": "^6.10.0",
|
||||
"eslint-plugin-import": "^2.20.1",
|
||||
|
@ -54,6 +59,7 @@
|
|||
"pre-commit": "^1.2.2",
|
||||
"prettier": "^2.0.5",
|
||||
"rimraf": "^3.0.2",
|
||||
"semantic-release": "^17.0.4"
|
||||
"semantic-release": "^17.0.4",
|
||||
"typescript": "^4.1.3"
|
||||
}
|
||||
}
|
||||
|
|
262
src/__tests__/index.test.ts
Normal file
262
src/__tests__/index.test.ts
Normal file
|
@ -0,0 +1,262 @@
|
|||
import * as childProcess from 'child_process'
|
||||
import { readFileSync } from 'fs'
|
||||
|
||||
import mockFS from 'mock-fs'
|
||||
|
||||
import runPackwatch from '..'
|
||||
|
||||
jest.mock('child_process')
|
||||
|
||||
function getPackOutput({ packageSize, unpackedSize }) {
|
||||
return `
|
||||
npm notice
|
||||
npm notice 📦 footprint@0.0.0
|
||||
npm notice === Tarball Contents ===
|
||||
npm notice 732B package.json
|
||||
npm notice 1.8kB dist/helpers.js
|
||||
npm notice 1.9kB dist/index.js
|
||||
npm notice === Tarball Details ===
|
||||
npm notice name: footprint
|
||||
npm notice version: 0.0.0
|
||||
npm notice filename: footprint-0.0.0.tgz
|
||||
npm notice package size: ${packageSize}
|
||||
npm notice unpacked size: ${unpackedSize}
|
||||
npm notice shasum: bdf33d471543cd8126338a82a27b16a9010b8dbd
|
||||
npm notice integrity: sha512-ZZvTg9GVcJw8J[...]bkE0xlqQhlt4Q==
|
||||
npm notice total files: 3
|
||||
npm notice
|
||||
`
|
||||
}
|
||||
|
||||
function getManifest() {
|
||||
try {
|
||||
return JSON.parse(readFileSync('.packwatch.json', { encoding: 'utf8' }))
|
||||
} catch {
|
||||
/* No manifest */
|
||||
}
|
||||
}
|
||||
|
||||
function setupMockFS({
|
||||
hasPackageJSON,
|
||||
hasManifest,
|
||||
manifestLimit,
|
||||
manifestSize,
|
||||
}) {
|
||||
const fs = {}
|
||||
|
||||
if (hasPackageJSON) fs['package.json'] = '{}'
|
||||
|
||||
if (hasManifest)
|
||||
fs['.packwatch.json'] = JSON.stringify({
|
||||
unpackedSize: '0.5 B',
|
||||
limitBytes: manifestLimit,
|
||||
limit: `${manifestLimit} B`,
|
||||
packageSize: `${manifestSize} B`,
|
||||
packageSizeBytes: manifestSize,
|
||||
})
|
||||
mockFS(fs)
|
||||
}
|
||||
describe('Packwatch', () => {
|
||||
let mockLogger
|
||||
beforeEach(() => {
|
||||
mockFS({})
|
||||
mockLogger = jest.spyOn(global.console, 'log').mockImplementation()
|
||||
})
|
||||
|
||||
afterEach(jest.restoreAllMocks)
|
||||
|
||||
afterAll(mockFS.restore)
|
||||
|
||||
it('warns the user and errors if run away from package.json', () => {
|
||||
mockFS({})
|
||||
runPackwatch()
|
||||
|
||||
expect(mockLogger.mock.calls).toHaveLength(1)
|
||||
expect(mockLogger.mock.calls[0][0]).toMatchInlineSnapshot(
|
||||
'"🤔 There is no package.json file here. Are you in the root directory of your project?"',
|
||||
)
|
||||
})
|
||||
|
||||
describe('without manifest', () => {
|
||||
beforeEach(() => {
|
||||
setupMockFS({ hasPackageJSON: true })
|
||||
})
|
||||
|
||||
it.each(['1 B', '1.1 B', '1 kB', '1.1 kB', '1 mB', '1.1 mB'])(
|
||||
'generates the initial manifest properly (size = %s)',
|
||||
mockSize => {
|
||||
jest.spyOn(childProcess, 'spawnSync').mockReturnValue({
|
||||
stderr: getPackOutput({
|
||||
packageSize: mockSize,
|
||||
unpackedSize: mockSize,
|
||||
}),
|
||||
})
|
||||
const returnCode = runPackwatch()
|
||||
const manifest = getManifest()
|
||||
expect(returnCode).toEqual(1)
|
||||
expect(manifest).toEqual({
|
||||
limit: mockSize,
|
||||
packageSize: mockSize,
|
||||
unpackedSize: mockSize,
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
it('outputs expected messaging', () => {
|
||||
jest.spyOn(childProcess, 'spawnSync').mockReturnValue({
|
||||
stderr: getPackOutput({
|
||||
packageSize: '1 B',
|
||||
unpackedSize: '2 B',
|
||||
}),
|
||||
})
|
||||
|
||||
runPackwatch()
|
||||
|
||||
expect(mockLogger.mock.calls).toHaveLength(2)
|
||||
expect(mockLogger.mock.calls[0][0]).toMatchInlineSnapshot(`
|
||||
"📝 No Manifest to compare against! Current package stats written to .packwatch.json!
|
||||
Package size (1 B) adopted as new limit."
|
||||
`)
|
||||
expect(mockLogger.mock.calls[1][0]).toMatchInlineSnapshot(
|
||||
'"❗ It looks like you ran PackWatch without a manifest. To prevent accidental passes in CI or hooks, packwatch will terminate with an error. If you are running packwatch for the first time in your project, this is expected!"',
|
||||
)
|
||||
})
|
||||
|
||||
it('outputs expected messaging when not updating the manifest', () => {
|
||||
jest.spyOn(childProcess, 'spawnSync').mockReturnValue({
|
||||
stderr: getPackOutput({
|
||||
packageSize: '1 B',
|
||||
unpackedSize: '2 B',
|
||||
}),
|
||||
})
|
||||
|
||||
runPackwatch({ isUpdatingManifest: true })
|
||||
|
||||
expect(mockLogger.mock.calls).toHaveLength(1)
|
||||
expect(mockLogger.mock.calls[0][0]).toMatchInlineSnapshot(`
|
||||
"📝 No Manifest to compare against! Current package stats written to .packwatch.json!
|
||||
Package size (1 B) adopted as new limit."
|
||||
`)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with manifest', () => {
|
||||
it('messages when the size is equal to the limit', () => {
|
||||
setupMockFS({
|
||||
hasPackageJSON: true,
|
||||
hasManifest: true,
|
||||
manifestLimit: 1,
|
||||
manifestSize: 1,
|
||||
})
|
||||
jest.spyOn(childProcess, 'spawnSync').mockReturnValue({
|
||||
stderr: getPackOutput({
|
||||
packageSize: '1 B',
|
||||
unpackedSize: '2 B',
|
||||
}),
|
||||
})
|
||||
runPackwatch()
|
||||
expect(mockLogger.mock.calls).toHaveLength(1)
|
||||
expect(mockLogger.mock.calls[0][0]).toMatchInlineSnapshot(
|
||||
'"📦 Nothing to report! Your package is the same size as the latest manifest reports! (Limit: 1 B)"',
|
||||
)
|
||||
})
|
||||
|
||||
it('messages when the size is lower than the limit (no growth)', () => {
|
||||
setupMockFS({
|
||||
hasPackageJSON: true,
|
||||
hasManifest: true,
|
||||
manifestLimit: 5,
|
||||
manifestSize: 1,
|
||||
})
|
||||
jest.spyOn(childProcess, 'spawnSync').mockReturnValue({
|
||||
stderr: getPackOutput({
|
||||
packageSize: '1 B',
|
||||
unpackedSize: '2 B',
|
||||
}),
|
||||
})
|
||||
runPackwatch()
|
||||
expect(mockLogger.mock.calls).toHaveLength(1)
|
||||
expect(mockLogger.mock.calls[0][0]).toMatchInlineSnapshot(
|
||||
'"📦 Nothing to report! Your package is the same size as the latest manifest reports! (Limit: 5 B)"',
|
||||
)
|
||||
})
|
||||
it('messages when the size is lower than the limit (growth)', () => {
|
||||
setupMockFS({
|
||||
hasPackageJSON: true,
|
||||
hasManifest: true,
|
||||
manifestLimit: 5,
|
||||
manifestSize: 2,
|
||||
})
|
||||
jest.spyOn(childProcess, 'spawnSync').mockReturnValue({
|
||||
stderr: getPackOutput({
|
||||
packageSize: '3 B',
|
||||
unpackedSize: '2 B',
|
||||
}),
|
||||
})
|
||||
runPackwatch()
|
||||
expect(mockLogger.mock.calls).toHaveLength(1)
|
||||
expect(mockLogger.mock.calls[0][0]).toMatchInlineSnapshot(
|
||||
'"📦 👀 Your package grew! 3 B > 2 B (Limit: 5 B)"',
|
||||
)
|
||||
})
|
||||
it('messages when the size is lower than the limit (shrinkage)', () => {
|
||||
setupMockFS({
|
||||
hasPackageJSON: true,
|
||||
hasManifest: true,
|
||||
manifestLimit: 5,
|
||||
manifestSize: 2,
|
||||
})
|
||||
jest.spyOn(childProcess, 'spawnSync').mockReturnValue({
|
||||
stderr: getPackOutput({
|
||||
packageSize: '1 B',
|
||||
unpackedSize: '2 B',
|
||||
}),
|
||||
})
|
||||
runPackwatch()
|
||||
expect(mockLogger.mock.calls).toHaveLength(1)
|
||||
expect(mockLogger.mock.calls[0][0]).toMatchInlineSnapshot(
|
||||
'"📦 💯 Your package shrank! 1 B < 2 B (Limit: 5 B)"',
|
||||
)
|
||||
})
|
||||
it('messages when the size exceeds the limit', () => {
|
||||
setupMockFS({
|
||||
hasPackageJSON: true,
|
||||
hasManifest: true,
|
||||
manifestLimit: 0.5,
|
||||
manifestSize: 0.5,
|
||||
})
|
||||
jest.spyOn(childProcess, 'spawnSync').mockReturnValue({
|
||||
stderr: getPackOutput({
|
||||
packageSize: '1 B',
|
||||
unpackedSize: '2 B',
|
||||
}),
|
||||
})
|
||||
runPackwatch()
|
||||
expect(mockLogger.mock.calls).toHaveLength(1)
|
||||
expect(mockLogger.mock.calls[0][0]).toMatchInlineSnapshot(`
|
||||
"🔥🔥📦🔥🔥 Your package exceeds the limit set in .packwatch.json! 1 B > 0.5 B
|
||||
Either update the limit by using the --update-manifest flag or trim down your packed files!"
|
||||
`)
|
||||
})
|
||||
|
||||
it('messages when updating the manifest', () => {
|
||||
setupMockFS({
|
||||
hasPackageJSON: true,
|
||||
hasManifest: true,
|
||||
manifestLimit: 0.5,
|
||||
manifestSize: 0.5,
|
||||
})
|
||||
jest.spyOn(childProcess, 'spawnSync').mockReturnValue({
|
||||
stderr: getPackOutput({
|
||||
packageSize: '1 B',
|
||||
unpackedSize: '2 B',
|
||||
}),
|
||||
})
|
||||
runPackwatch({ isUpdatingManifest: true })
|
||||
expect(mockLogger.mock.calls).toHaveLength(1)
|
||||
expect(mockLogger.mock.calls[0][0]).toMatchInlineSnapshot(
|
||||
'"📝 Updated the manifest! Package size: 1 B, Limit: 1 B"',
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
7
src/cli.ts
Normal file
7
src/cli.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import runPackwatch from '.'
|
||||
|
||||
const isUpdatingManifest = process.argv.includes('--update-manifest')
|
||||
const processExit = runPackwatch({ isUpdatingManifest })
|
||||
process.exit(processExit)
|
|
@ -1,73 +0,0 @@
|
|||
const { spawnSync } = require('child_process')
|
||||
const { readFileSync, writeFileSync } = require('fs')
|
||||
|
||||
const PACKAGE_SIZE_PATT = /package size:\s+([0-9]+\.?[0-9]*\s+[A-Za-z]+)/g
|
||||
const UNPACKED_SIZE_PATT = /unpacked size:\s+([0-9]+\.?[0-9]*\s+[A-Za-z]+)/g
|
||||
const SIZE_SUFFIX_PATT = /([A-Za-z]+)/
|
||||
const SIZE_MAGNITUDE_PATT = /([0-9]+\.?[0-9]*)/
|
||||
const MANIFEST_FILENAME = '.packwatch.json'
|
||||
|
||||
const FS_OPTIONS = { encoding: 'utf-8' }
|
||||
|
||||
function convertSizeToBytes(sizeString) {
|
||||
const sizeSuffix = SIZE_SUFFIX_PATT.exec(sizeString)[1]
|
||||
const sizeMagnitude = SIZE_MAGNITUDE_PATT.exec(sizeString)[1]
|
||||
|
||||
let multiplier = 1
|
||||
|
||||
if (sizeSuffix === 'kB') multiplier = 1000
|
||||
else if (sizeSuffix === 'mB') {
|
||||
multiplier = 1000000
|
||||
}
|
||||
|
||||
return multiplier * parseFloat(sizeMagnitude)
|
||||
}
|
||||
|
||||
function getCurrentPackageStats() {
|
||||
const { stderr } = spawnSync('npm', ['pack', '--dry-run'], FS_OPTIONS)
|
||||
const packageSize = PACKAGE_SIZE_PATT.exec(stderr)[1]
|
||||
const unpackedSize = UNPACKED_SIZE_PATT.exec(stderr)[1]
|
||||
|
||||
return {
|
||||
packageSize,
|
||||
unpackedSize,
|
||||
packageSizeBytes: convertSizeToBytes(packageSize),
|
||||
unpackedSizeBytes: convertSizeToBytes(unpackedSize),
|
||||
}
|
||||
}
|
||||
|
||||
function getPreviousPackageStats() {
|
||||
try {
|
||||
const currentManifest = readFileSync(MANIFEST_FILENAME, FS_OPTIONS)
|
||||
const parsedManifest = JSON.parse(currentManifest)
|
||||
return {
|
||||
...parsedManifest,
|
||||
packageSizeBytes: convertSizeToBytes(parsedManifest.packageSize),
|
||||
unpackedSizeBytes: convertSizeToBytes(parsedManifest.unpackedSize),
|
||||
limitBytes: convertSizeToBytes(parsedManifest.limit),
|
||||
}
|
||||
} catch (e) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function createOrUpdateManifest({ previous, current, updateLimit = false }) {
|
||||
const { limit } = previous || {}
|
||||
const { packageSize, unpackedSize } = current
|
||||
|
||||
const newManifest = {
|
||||
limit: updateLimit ? packageSize : limit || packageSize,
|
||||
packageSize: packageSize,
|
||||
unpackedSize: unpackedSize,
|
||||
}
|
||||
|
||||
writeFileSync(MANIFEST_FILENAME, JSON.stringify(newManifest))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createOrUpdateManifest,
|
||||
getPreviousPackageStats,
|
||||
getCurrentPackageStats,
|
||||
convertSizeToBytes,
|
||||
MANIFEST_FILENAME,
|
||||
}
|
8
src/index.d.ts
vendored
Normal file
8
src/index.d.ts
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
export type Report = {
|
||||
packageSize: string
|
||||
unpackedSize?: string
|
||||
packageSizeBytes?: number
|
||||
unpackedSizeBytes?: number
|
||||
limit?: string
|
||||
limitBytes?: number
|
||||
}
|
106
src/index.js
106
src/index.js
|
@ -1,106 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const { existsSync } = require('fs')
|
||||
|
||||
const {
|
||||
MANIFEST_FILENAME,
|
||||
getCurrentPackageStats,
|
||||
getPreviousPackageStats,
|
||||
createOrUpdateManifest,
|
||||
} = require('./helpers')
|
||||
|
||||
if (!existsSync('package.json')) {
|
||||
console.log(
|
||||
'🤔 There is no package.json file here. Are you in the root directory of your project?',
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const isUpdatingManifest = process.argv.includes('--update-manifest')
|
||||
|
||||
const currentStats = getCurrentPackageStats()
|
||||
|
||||
/*
|
||||
* If there is no manifest file yet, we can use the current package stats as
|
||||
* a base to build one. The current package size becomes the limit.
|
||||
*/
|
||||
|
||||
if (!existsSync(MANIFEST_FILENAME)) {
|
||||
createOrUpdateManifest({ current: currentStats })
|
||||
console.log(
|
||||
`📝 No Manifest to compare against! Current package stats written to ${MANIFEST_FILENAME}!`,
|
||||
)
|
||||
console.log(
|
||||
`Package size (${currentStats.packageSize}) adopted as new limit.`,
|
||||
)
|
||||
|
||||
if (!isUpdatingManifest) {
|
||||
console.log(
|
||||
'❗ It looks like you ran PackWatch without a manifest. To prevent accidental passes in CI or hooks, packwatch will terminate with an error. If you are running packwatch for the first time in your project, this is expected!',
|
||||
)
|
||||
}
|
||||
// If the update flag wasn't specified, exit with a non-zero code so we
|
||||
// don't "accidentally" pass CI builds if the manifest didn't exist
|
||||
process.exit(isUpdatingManifest ? 0 : 1)
|
||||
}
|
||||
|
||||
const previousStats = getPreviousPackageStats()
|
||||
const { packageSizeBytes, packageSize } = currentStats
|
||||
const {
|
||||
packageSize: previousSize,
|
||||
packageSizeBytes: previousSizeBytes,
|
||||
limit,
|
||||
limitBytes,
|
||||
} = previousStats
|
||||
const hasExceededLimit = packageSizeBytes > limitBytes
|
||||
|
||||
/*
|
||||
* If we are updating the manifest, we can write right away and terminate.
|
||||
*/
|
||||
|
||||
if (isUpdatingManifest) {
|
||||
createOrUpdateManifest({
|
||||
previous: previousStats,
|
||||
current: currentStats,
|
||||
updateLimit: true,
|
||||
})
|
||||
console.log(
|
||||
`📝 Updated the manifest! Package size: ${packageSize}, Limit: ${packageSize}`,
|
||||
)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a manifest file and the current package busts its limit
|
||||
* we signal it and terminate with an error.
|
||||
*/
|
||||
|
||||
if (hasExceededLimit) {
|
||||
console.log(
|
||||
`🔥🔥📦🔥🔥 Your package exceeds the limit set in ${MANIFEST_FILENAME}! ${packageSize} > ${limit}`,
|
||||
)
|
||||
console.log(
|
||||
'Either update the limit by using the --update-manifest flag or trim down your packed files!',
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a manifest file and the limit is not busted, we give
|
||||
* the user some feedback on how the current package compares with
|
||||
* the previous one.
|
||||
*/
|
||||
|
||||
if (packageSizeBytes > previousSizeBytes) {
|
||||
console.log(
|
||||
`📦 👀 Your package grew! ${packageSize} > ${previousSize} (Limit: ${limit})`,
|
||||
)
|
||||
} else if (packageSizeBytes < previousSizeBytes) {
|
||||
console.log(
|
||||
`📦 💯 Your package shrank! ${packageSize} < ${previousSize} (Limit: ${limit})`,
|
||||
)
|
||||
} else {
|
||||
console.log(
|
||||
`📦 Nothing to report! Your package is the same size as the latest manifest reports! (Limit: ${limit})`,
|
||||
)
|
||||
}
|
|
@ -1,177 +0,0 @@
|
|||
const childProcess = require('child_process')
|
||||
const { readFileSync } = require('fs')
|
||||
|
||||
const mockFS = require('mock-fs')
|
||||
|
||||
jest.mock('child_process')
|
||||
childProcess.spawnSync = jest.fn(() => ({ stderr: mockPackOutput }))
|
||||
|
||||
const {
|
||||
MANIFEST_FILENAME,
|
||||
convertSizeToBytes,
|
||||
getCurrentPackageStats,
|
||||
getPreviousPackageStats,
|
||||
createOrUpdateManifest,
|
||||
} = require('./helpers')
|
||||
|
||||
const mockPackageSize = '1.1 kB'
|
||||
const mockUnpackedSize = '9000 kB'
|
||||
|
||||
const mockPackOutput = `
|
||||
npm notice
|
||||
npm notice 📦 footprint@0.0.0
|
||||
npm notice === Tarball Contents ===
|
||||
npm notice 732B package.json
|
||||
npm notice 1.8kB dist/helpers.js
|
||||
npm notice 1.9kB dist/index.js
|
||||
npm notice === Tarball Details ===
|
||||
npm notice name: footprint
|
||||
npm notice version: 0.0.0
|
||||
npm notice filename: footprint-0.0.0.tgz
|
||||
npm notice package size: ${mockPackageSize}
|
||||
npm notice unpacked size: ${mockUnpackedSize}
|
||||
npm notice shasum: bdf33d471543cd8126338a82a27b16a9010b8dbd
|
||||
npm notice integrity: sha512-ZZvTg9GVcJw8J[...]bkE0xlqQhlt4Q==
|
||||
npm notice total files: 3
|
||||
npm notice
|
||||
`
|
||||
describe('Helpers', () => {
|
||||
beforeEach(() => {
|
||||
mockFS.restore()
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
||||
afterAll(mockFS.restore)
|
||||
|
||||
describe('Size string conversion', () => {
|
||||
it.each`
|
||||
sizeString | expectedValue
|
||||
${'1 B'} | ${1}
|
||||
${'1.1 B'} | ${1.1}
|
||||
${'1 kB'} | ${1000}
|
||||
${'1.1kB'} | ${1100}
|
||||
${'1 mB'} | ${1000000}
|
||||
${'1.1 mB'} | ${1100000}
|
||||
`(
|
||||
'converts $sizeString properly to $expectedValue bytes',
|
||||
({ sizeString, expectedValue }) => {
|
||||
expect(convertSizeToBytes(sizeString)).toEqual(expectedValue)
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
describe('Current package statistics', () => {
|
||||
it('constructs the current package report properly', () => {
|
||||
const packageSizeBytes = 1100
|
||||
const unpackedSizeBytes = 9000000
|
||||
|
||||
expect(getCurrentPackageStats()).toEqual({
|
||||
packageSize: mockPackageSize,
|
||||
packageSizeBytes,
|
||||
unpackedSize: mockUnpackedSize,
|
||||
unpackedSizeBytes,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Previous package statistics', () => {
|
||||
it('constructs the previous package report properly', () => {
|
||||
const packageSize = '0.9 kB'
|
||||
const packageSizeBytes = 900
|
||||
const unpackedSize = '90 kB'
|
||||
const unpackedSizeBytes = 90000
|
||||
const limit = '1 kB'
|
||||
const limitBytes = 1000
|
||||
const mockReport = { packageSize, unpackedSize, limit }
|
||||
mockFS({ [MANIFEST_FILENAME]: JSON.stringify(mockReport) })
|
||||
|
||||
expect(getPreviousPackageStats()).toEqual({
|
||||
packageSize,
|
||||
packageSizeBytes,
|
||||
unpackedSize,
|
||||
unpackedSizeBytes,
|
||||
limit,
|
||||
limitBytes,
|
||||
})
|
||||
})
|
||||
|
||||
it('returns an empty manifest if it fails to reads the manifest file', () => {
|
||||
mockFS({
|
||||
[MANIFEST_FILENAME]: 'not valid JSON',
|
||||
})
|
||||
|
||||
expect(getPreviousPackageStats()).toEqual({})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Creating or updating the manifest', () => {
|
||||
const currentStats = {
|
||||
packageSize: '1 kB',
|
||||
unpackedSize: '10 kB',
|
||||
}
|
||||
|
||||
const previousManifest = {
|
||||
limit: '2 kB',
|
||||
packageSize: '1.5 kB',
|
||||
}
|
||||
it('creates a anifest from the current data if no previous data is provided', () => {
|
||||
mockFS({})
|
||||
|
||||
createOrUpdateManifest({ current: currentStats })
|
||||
|
||||
const writtenManifest = readFileSync(MANIFEST_FILENAME, {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
|
||||
expect(JSON.parse(writtenManifest)).toEqual({
|
||||
packageSize: currentStats.packageSize,
|
||||
unpackedSize: currentStats.unpackedSize,
|
||||
limit: currentStats.packageSize,
|
||||
})
|
||||
})
|
||||
|
||||
it('updates the previous manifest sizes if previous data exists', () => {
|
||||
mockFS({
|
||||
[MANIFEST_FILENAME]: JSON.stringify(previousManifest),
|
||||
})
|
||||
|
||||
createOrUpdateManifest({
|
||||
current: currentStats,
|
||||
previous: previousManifest,
|
||||
updateLimit: false,
|
||||
})
|
||||
|
||||
const writtenManifest = readFileSync(MANIFEST_FILENAME, {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
|
||||
expect(JSON.parse(writtenManifest)).toEqual({
|
||||
packageSize: currentStats.packageSize,
|
||||
unpackedSize: currentStats.unpackedSize,
|
||||
limit: previousManifest.limit,
|
||||
})
|
||||
})
|
||||
|
||||
it('updates the previous manifest sizes and limit if previous data exists and updateLimit is set', () => {
|
||||
mockFS({
|
||||
[MANIFEST_FILENAME]: JSON.stringify(previousManifest),
|
||||
})
|
||||
|
||||
createOrUpdateManifest({
|
||||
current: currentStats,
|
||||
previous: previousManifest,
|
||||
updateLimit: true,
|
||||
})
|
||||
|
||||
const writtenManifest = readFileSync(MANIFEST_FILENAME, {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
|
||||
expect(JSON.parse(writtenManifest)).toEqual({
|
||||
packageSize: currentStats.packageSize,
|
||||
unpackedSize: currentStats.unpackedSize,
|
||||
limit: currentStats.packageSize,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
177
src/index.ts
Normal file
177
src/index.ts
Normal file
|
@ -0,0 +1,177 @@
|
|||
import { spawnSync } from 'child_process'
|
||||
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
||||
|
||||
import { Report } from './index.d'
|
||||
|
||||
const PACKAGE_SIZE_PATT = /package size:\s*([0-9]+\.?[0-9]*\s+[A-Za-z]{1,2})/
|
||||
const UNPACKED_SIZE_PATT = /unpacked size:\s*([0-9]+\.?[0-9]*\s+[A-Za-z]{1,2})/
|
||||
const SIZE_SUFFIX_PATT = /([A-Za-z]+)/
|
||||
const SIZE_MAGNITUDE_PATT = /([0-9]+\.?[0-9]*)/
|
||||
|
||||
const MANIFEST_FILENAME = '.packwatch.json'
|
||||
|
||||
function convertSizeToBytes(sizeString: string): number {
|
||||
const sizeSuffix = SIZE_SUFFIX_PATT.exec(sizeString)[1]
|
||||
const sizeMagnitude = SIZE_MAGNITUDE_PATT.exec(sizeString)[1]
|
||||
|
||||
let multiplier = 1
|
||||
|
||||
if (sizeSuffix === 'kB') multiplier = 1000
|
||||
else if (sizeSuffix === 'mB') {
|
||||
multiplier = 1000000
|
||||
}
|
||||
|
||||
return multiplier * parseFloat(sizeMagnitude)
|
||||
}
|
||||
|
||||
function getCurrentPackageStats(): Report {
|
||||
const { stderr } = spawnSync('npm', ['pack', '--dry-run'], {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
const stderrString = String(stderr)
|
||||
const packageSize = PACKAGE_SIZE_PATT.exec(stderrString)[1]
|
||||
const unpackedSize = UNPACKED_SIZE_PATT.exec(stderrString)[1]
|
||||
|
||||
return {
|
||||
packageSize,
|
||||
unpackedSize,
|
||||
packageSizeBytes: convertSizeToBytes(packageSize),
|
||||
unpackedSizeBytes: convertSizeToBytes(unpackedSize),
|
||||
}
|
||||
}
|
||||
|
||||
function getPreviousPackageStats(): Report | null {
|
||||
try {
|
||||
const currentManifest = readFileSync(MANIFEST_FILENAME, {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
const parsedManifest = JSON.parse(currentManifest)
|
||||
return {
|
||||
...parsedManifest,
|
||||
packageSizeBytes: convertSizeToBytes(parsedManifest.packageSize),
|
||||
unpackedSizeBytes: convertSizeToBytes(parsedManifest.unpackedSize),
|
||||
limitBytes: convertSizeToBytes(parsedManifest.limit),
|
||||
}
|
||||
} catch {
|
||||
/* No manifest */
|
||||
}
|
||||
}
|
||||
|
||||
function createOrUpdateManifest({
|
||||
previous,
|
||||
current,
|
||||
updateLimit = false,
|
||||
}: {
|
||||
previous?: Report
|
||||
current: Report
|
||||
updateLimit?: boolean
|
||||
}): void {
|
||||
const { limit } = previous || {}
|
||||
const { packageSize, unpackedSize } = current
|
||||
|
||||
const newManifest = {
|
||||
limit: updateLimit ? packageSize : limit || packageSize,
|
||||
packageSize: packageSize,
|
||||
unpackedSize: unpackedSize,
|
||||
}
|
||||
|
||||
writeFileSync(MANIFEST_FILENAME, JSON.stringify(newManifest))
|
||||
}
|
||||
export default function run(
|
||||
{
|
||||
manifestFn = MANIFEST_FILENAME,
|
||||
isUpdatingManifest,
|
||||
}: { manifestFn?: string; isUpdatingManifest?: boolean } = {
|
||||
manifestFn: MANIFEST_FILENAME,
|
||||
isUpdatingManifest: false,
|
||||
},
|
||||
): number {
|
||||
if (!existsSync('package.json')) {
|
||||
console.log(
|
||||
'🤔 There is no package.json file here. Are you in the root directory of your project?',
|
||||
)
|
||||
return 1
|
||||
}
|
||||
|
||||
const currentStats = getCurrentPackageStats()
|
||||
|
||||
/*
|
||||
* If there is no manifest file yet, we can use the current package stats as
|
||||
* a base to build one. The current package size becomes the limit.
|
||||
*/
|
||||
|
||||
if (!existsSync(manifestFn)) {
|
||||
createOrUpdateManifest({ current: currentStats })
|
||||
console.log(
|
||||
`📝 No Manifest to compare against! Current package stats written to ${MANIFEST_FILENAME}!\nPackage size (${currentStats.packageSize}) adopted as new limit.`,
|
||||
)
|
||||
|
||||
if (!isUpdatingManifest) {
|
||||
console.log(
|
||||
'❗ It looks like you ran PackWatch without a manifest. To prevent accidental passes in CI or hooks, packwatch will terminate with an error. If you are running packwatch for the first time in your project, this is expected!',
|
||||
)
|
||||
}
|
||||
// If the update flag wasn't specified, exit with a non-zero code so we
|
||||
// don't "accidentally" pass CI builds if the manifest didn't exist
|
||||
return isUpdatingManifest ? 0 : 1
|
||||
}
|
||||
|
||||
const previousStats = getPreviousPackageStats()
|
||||
const { packageSizeBytes, packageSize } = currentStats
|
||||
const {
|
||||
packageSize: previousSize,
|
||||
packageSizeBytes: previousSizeBytes,
|
||||
limit,
|
||||
limitBytes,
|
||||
} = previousStats
|
||||
const hasExceededLimit = packageSizeBytes > limitBytes
|
||||
|
||||
/*
|
||||
* If we are updating the manifest, we can write right away and terminate.
|
||||
*/
|
||||
|
||||
if (isUpdatingManifest) {
|
||||
createOrUpdateManifest({
|
||||
previous: previousStats,
|
||||
current: currentStats,
|
||||
updateLimit: true,
|
||||
})
|
||||
console.log(
|
||||
`📝 Updated the manifest! Package size: ${packageSize}, Limit: ${packageSize}`,
|
||||
)
|
||||
return 0
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a manifest file and the current package busts its limit
|
||||
* we signal it and terminate with an error.
|
||||
*/
|
||||
|
||||
if (hasExceededLimit) {
|
||||
console.log(
|
||||
`🔥🔥📦🔥🔥 Your package exceeds the limit set in ${MANIFEST_FILENAME}! ${packageSize} > ${limit}\nEither update the limit by using the --update-manifest flag or trim down your packed files!`,
|
||||
)
|
||||
return 1
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a manifest file and the limit is not busted, we give
|
||||
* the user some feedback on how the current package compares with
|
||||
* the previous one.
|
||||
*/
|
||||
|
||||
if (packageSizeBytes > previousSizeBytes) {
|
||||
console.log(
|
||||
`📦 👀 Your package grew! ${packageSize} > ${previousSize} (Limit: ${limit})`,
|
||||
)
|
||||
} else if (packageSizeBytes < previousSizeBytes) {
|
||||
console.log(
|
||||
`📦 💯 Your package shrank! ${packageSize} < ${previousSize} (Limit: ${limit})`,
|
||||
)
|
||||
} else {
|
||||
console.log(
|
||||
`📦 Nothing to report! Your package is the same size as the latest manifest reports! (Limit: ${limit})`,
|
||||
)
|
||||
}
|
||||
return 0
|
||||
}
|
247
yarn.lock
247
yarn.lock
|
@ -103,6 +103,17 @@
|
|||
"@babel/helper-replace-supers" "^7.10.4"
|
||||
"@babel/helper-split-export-declaration" "^7.10.4"
|
||||
|
||||
"@babel/helper-create-class-features-plugin@^7.12.1":
|
||||
version "7.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e"
|
||||
integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==
|
||||
dependencies:
|
||||
"@babel/helper-function-name" "^7.10.4"
|
||||
"@babel/helper-member-expression-to-functions" "^7.12.1"
|
||||
"@babel/helper-optimise-call-expression" "^7.10.4"
|
||||
"@babel/helper-replace-supers" "^7.12.1"
|
||||
"@babel/helper-split-export-declaration" "^7.10.4"
|
||||
|
||||
"@babel/helper-create-regexp-features-plugin@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8"
|
||||
|
@ -286,6 +297,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
|
||||
integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==
|
||||
|
||||
"@babel/helper-validator-option@^7.12.1":
|
||||
version "7.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9"
|
||||
integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A==
|
||||
|
||||
"@babel/helper-wrap-function@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87"
|
||||
|
@ -517,6 +533,13 @@
|
|||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
|
||||
"@babel/plugin-syntax-typescript@^7.12.1":
|
||||
version "7.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.1.tgz#460ba9d77077653803c3dd2e673f76d66b4029e5"
|
||||
integrity sha512-UZNEcCY+4Dp9yYRCAHrHDU+9ZXLYaY9MgBXSRLkB9WjYFRR6quJBumfVrEkUxrePPBwFcpWfNKXqVRQQtm7mMA==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
|
||||
"@babel/plugin-transform-arrow-functions@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd"
|
||||
|
@ -754,6 +777,15 @@
|
|||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
|
||||
"@babel/plugin-transform-typescript@^7.12.1":
|
||||
version "7.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.1.tgz#d92cc0af504d510e26a754a7dbc2e5c8cd9c7ab4"
|
||||
integrity sha512-VrsBByqAIntM+EYMqSm59SiMEf7qkmI9dqMt6RbD/wlwueWmYcI0FFK5Fj47pP6DRZm+3teXjosKlwcZJ5lIMw==
|
||||
dependencies:
|
||||
"@babel/helper-create-class-features-plugin" "^7.12.1"
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
"@babel/plugin-syntax-typescript" "^7.12.1"
|
||||
|
||||
"@babel/plugin-transform-unicode-escapes@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007"
|
||||
|
@ -854,6 +886,15 @@
|
|||
"@babel/types" "^7.4.4"
|
||||
esutils "^2.0.2"
|
||||
|
||||
"@babel/preset-typescript@^7.12.7":
|
||||
version "7.12.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.12.7.tgz#fc7df8199d6aae747896f1e6c61fc872056632a3"
|
||||
integrity sha512-nOoIqIqBmHBSEgBXWR4Dv/XBehtIFcw9PqZw6rFYuKrzsZmOQm3PR5siLBnKZFEsDb03IegG8nSjU/iXXXYRmw==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.10.4"
|
||||
"@babel/helper-validator-option" "^7.12.1"
|
||||
"@babel/plugin-transform-typescript" "^7.12.1"
|
||||
|
||||
"@babel/runtime@^7.6.3":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308"
|
||||
|
@ -1109,6 +1150,17 @@
|
|||
"@types/yargs" "^15.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@jest/types@^26.6.2":
|
||||
version "26.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e"
|
||||
integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==
|
||||
dependencies:
|
||||
"@types/istanbul-lib-coverage" "^2.0.0"
|
||||
"@types/istanbul-reports" "^3.0.0"
|
||||
"@types/node" "*"
|
||||
"@types/yargs" "^15.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents":
|
||||
version "2.1.8-no-fsevents"
|
||||
resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz#da7c3996b8e6e19ebd14d82eaced2313e7769f9b"
|
||||
|
@ -1419,6 +1471,21 @@
|
|||
"@types/istanbul-lib-coverage" "*"
|
||||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/istanbul-reports@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821"
|
||||
integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==
|
||||
dependencies:
|
||||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/jest@^26.0.19":
|
||||
version "26.0.19"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.19.tgz#e6fa1e3def5842ec85045bd5210e9bb8289de790"
|
||||
integrity sha512-jqHoirTG61fee6v6rwbnEuKhpSKih0tuhqeFbCmMmErhtu3BYlOZaXWjffgOstMM4S/3iQD31lI5bGLTrs97yQ==
|
||||
dependencies:
|
||||
jest-diff "^26.0.0"
|
||||
pretty-format "^26.0.0"
|
||||
|
||||
"@types/json-schema@^7.0.3":
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
|
||||
|
@ -1439,6 +1506,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.7.tgz#1628e6461ba8cc9b53196dfeaeec7b07fa6eea99"
|
||||
integrity sha512-Uo4chgKbnPNlxQwoFmYIwctkQVkMMmsAoGGU4JKwLuvBefF0pCq4FybNSnfkfRCpC7ZW7kttcC/TrRtAJsvGtg==
|
||||
|
||||
"@types/node@^14.14.13":
|
||||
version "14.14.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.13.tgz#9e425079799322113ae8477297ae6ef51b8e0cdf"
|
||||
integrity sha512-vbxr0VZ8exFMMAjCW8rJwaya0dMCDyYW2ZRdTyjtrCvJoENMpdUHOT/eTzvgyA5ZnqRZ/sI0NwqAxNHKYokLJQ==
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
|
||||
|
@ -1476,6 +1548,31 @@
|
|||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^4.9.1":
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.9.1.tgz#66758cbe129b965fe9c63b04b405d0cf5280868b"
|
||||
integrity sha512-QRLDSvIPeI1pz5tVuurD+cStNR4sle4avtHhxA+2uyixWGFjKzJ+EaFVRW6dA/jOgjV5DTAjOxboQkRDE8cRlQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/experimental-utils" "4.9.1"
|
||||
"@typescript-eslint/scope-manager" "4.9.1"
|
||||
debug "^4.1.1"
|
||||
functional-red-black-tree "^1.0.1"
|
||||
regexpp "^3.0.0"
|
||||
semver "^7.3.2"
|
||||
tsutils "^3.17.1"
|
||||
|
||||
"@typescript-eslint/experimental-utils@4.9.1":
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.9.1.tgz#86633e8395191d65786a808dc3df030a55267ae2"
|
||||
integrity sha512-c3k/xJqk0exLFs+cWSJxIjqLYwdHCuLWhnpnikmPQD2+NGAx9KjLYlBDcSI81EArh9FDYSL6dslAUSwILeWOxg==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.3"
|
||||
"@typescript-eslint/scope-manager" "4.9.1"
|
||||
"@typescript-eslint/types" "4.9.1"
|
||||
"@typescript-eslint/typescript-estree" "4.9.1"
|
||||
eslint-scope "^5.0.0"
|
||||
eslint-utils "^2.0.0"
|
||||
|
||||
"@typescript-eslint/experimental-utils@^2.5.0":
|
||||
version "2.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.21.0.tgz#71de390a3ec00b280b69138d80733406e6e86bfa"
|
||||
|
@ -1485,6 +1582,29 @@
|
|||
"@typescript-eslint/typescript-estree" "2.21.0"
|
||||
eslint-scope "^5.0.0"
|
||||
|
||||
"@typescript-eslint/parser@^4.9.1":
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.9.1.tgz#2d74c4db5dd5117379a9659081a4d1ec02629055"
|
||||
integrity sha512-Gv2VpqiomvQ2v4UL+dXlQcZ8zCX4eTkoIW+1aGVWT6yTO+6jbxsw7yQl2z2pPl/4B9qa5JXeIbhJpONKjXIy3g==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "4.9.1"
|
||||
"@typescript-eslint/types" "4.9.1"
|
||||
"@typescript-eslint/typescript-estree" "4.9.1"
|
||||
debug "^4.1.1"
|
||||
|
||||
"@typescript-eslint/scope-manager@4.9.1":
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.9.1.tgz#cc2fde310b3f3deafe8436a924e784eaab265103"
|
||||
integrity sha512-sa4L9yUfD/1sg9Kl8OxPxvpUcqxKXRjBeZxBuZSSV1v13hjfEJkn84n0An2hN8oLQ1PmEl2uA6FkI07idXeFgQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.9.1"
|
||||
"@typescript-eslint/visitor-keys" "4.9.1"
|
||||
|
||||
"@typescript-eslint/types@4.9.1":
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.9.1.tgz#a1a7dd80e4e5ac2c593bc458d75dd1edaf77faa2"
|
||||
integrity sha512-fjkT+tXR13ks6Le7JiEdagnwEFc49IkOyys7ueWQ4O8k4quKPwPJudrwlVOJCUQhXo45PrfIvIarcrEjFTNwUA==
|
||||
|
||||
"@typescript-eslint/typescript-estree@2.21.0":
|
||||
version "2.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.21.0.tgz#7e4be29f2e338195a2e8c818949ed0ff727cc943"
|
||||
|
@ -1498,6 +1618,28 @@
|
|||
semver "^6.3.0"
|
||||
tsutils "^3.17.1"
|
||||
|
||||
"@typescript-eslint/typescript-estree@4.9.1":
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.9.1.tgz#6e5b86ff5a5f66809e1f347469fadeec69ac50bf"
|
||||
integrity sha512-bzP8vqwX6Vgmvs81bPtCkLtM/Skh36NE6unu6tsDeU/ZFoYthlTXbBmpIrvosgiDKlWTfb2ZpPELHH89aQjeQw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.9.1"
|
||||
"@typescript-eslint/visitor-keys" "4.9.1"
|
||||
debug "^4.1.1"
|
||||
globby "^11.0.1"
|
||||
is-glob "^4.0.1"
|
||||
lodash "^4.17.15"
|
||||
semver "^7.3.2"
|
||||
tsutils "^3.17.1"
|
||||
|
||||
"@typescript-eslint/visitor-keys@4.9.1":
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.9.1.tgz#d76374a58c4ead9e92b454d186fea63487b25ae1"
|
||||
integrity sha512-9gspzc6UqLQHd7lXQS7oWs+hrYggspv/rk6zzEMhCbYwPE/sF7oxo7GAjkS35Tdlt7wguIG+ViWCPtVZHz/ybQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.9.1"
|
||||
eslint-visitor-keys "^2.0.0"
|
||||
|
||||
JSONStream@^1.0.4, JSONStream@^1.3.4, JSONStream@^1.3.5:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
|
||||
|
@ -2637,7 +2779,7 @@ debug@^3.1.0:
|
|||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debuglog@*, debuglog@^1.0.1:
|
||||
debuglog@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
|
||||
integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
|
||||
|
@ -2759,6 +2901,11 @@ diff-sequences@^26.0.0:
|
|||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.0.0.tgz#0760059a5c287637b842bd7085311db7060e88a6"
|
||||
integrity sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg==
|
||||
|
||||
diff-sequences@^26.6.2:
|
||||
version "26.6.2"
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1"
|
||||
integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==
|
||||
|
||||
dir-glob@^3.0.0, dir-glob@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
||||
|
@ -3056,7 +3203,7 @@ eslint-scope@^5.0.0, eslint-scope@^5.1.0:
|
|||
esrecurse "^4.1.0"
|
||||
estraverse "^4.1.1"
|
||||
|
||||
eslint-utils@^2.1.0:
|
||||
eslint-utils@^2.0.0, eslint-utils@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
|
||||
integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
|
||||
|
@ -3068,6 +3215,11 @@ eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
|
|||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
|
||||
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
|
||||
|
||||
eslint-visitor-keys@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
|
||||
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
|
||||
|
||||
eslint@^7.0.0:
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.6.0.tgz#522d67cfaea09724d96949c70e7a0550614d64d6"
|
||||
|
@ -3689,6 +3841,18 @@ globby@^11.0.0:
|
|||
merge2 "^1.3.0"
|
||||
slash "^3.0.0"
|
||||
|
||||
globby@^11.0.1:
|
||||
version "11.0.1"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357"
|
||||
integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==
|
||||
dependencies:
|
||||
array-union "^2.1.0"
|
||||
dir-glob "^3.0.1"
|
||||
fast-glob "^3.1.1"
|
||||
ignore "^5.1.4"
|
||||
merge2 "^1.3.0"
|
||||
slash "^3.0.0"
|
||||
|
||||
got@^6.7.1:
|
||||
version "6.7.1"
|
||||
resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
|
||||
|
@ -3955,7 +4119,7 @@ import-local@^3.0.2:
|
|||
pkg-dir "^4.2.0"
|
||||
resolve-cwd "^3.0.0"
|
||||
|
||||
imurmurhash@*, imurmurhash@^0.1.4:
|
||||
imurmurhash@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
||||
|
@ -4489,6 +4653,16 @@ jest-config@^26.2.2:
|
|||
micromatch "^4.0.2"
|
||||
pretty-format "^26.2.0"
|
||||
|
||||
jest-diff@^26.0.0:
|
||||
version "26.6.2"
|
||||
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394"
|
||||
integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
diff-sequences "^26.6.2"
|
||||
jest-get-type "^26.3.0"
|
||||
pretty-format "^26.6.2"
|
||||
|
||||
jest-diff@^26.2.0:
|
||||
version "26.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.2.0.tgz#dee62c771adbb23ae585f3f1bd289a6e8ef4f298"
|
||||
|
@ -4547,6 +4721,11 @@ jest-get-type@^26.0.0:
|
|||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039"
|
||||
integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg==
|
||||
|
||||
jest-get-type@^26.3.0:
|
||||
version "26.3.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0"
|
||||
integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==
|
||||
|
||||
jest-haste-map@^26.2.2:
|
||||
version "26.2.2"
|
||||
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.2.2.tgz#6d4267b1903854bfdf6a871419f35a82f03ae71e"
|
||||
|
@ -5209,11 +5388,6 @@ lockfile@^1.0.4:
|
|||
dependencies:
|
||||
signal-exit "^3.0.2"
|
||||
|
||||
lodash._baseindexof@*:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
|
||||
integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=
|
||||
|
||||
lodash._baseuniq@~4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
|
||||
|
@ -5222,33 +5396,11 @@ lodash._baseuniq@~4.6.0:
|
|||
lodash._createset "~4.0.0"
|
||||
lodash._root "~3.0.0"
|
||||
|
||||
lodash._bindcallback@*:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
|
||||
integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4=
|
||||
|
||||
lodash._cacheindexof@*:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
|
||||
integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=
|
||||
|
||||
lodash._createcache@*:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
|
||||
integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=
|
||||
dependencies:
|
||||
lodash._getnative "^3.0.0"
|
||||
|
||||
lodash._createset@~4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
|
||||
integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=
|
||||
|
||||
lodash._getnative@*, lodash._getnative@^3.0.0:
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
|
||||
integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=
|
||||
|
||||
lodash._root@~3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
|
||||
|
@ -5284,11 +5436,6 @@ lodash.isstring@^4.0.1:
|
|||
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
|
||||
integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
|
||||
|
||||
lodash.restparam@*:
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
|
||||
integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=
|
||||
|
||||
lodash.sortby@^4.7.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
||||
|
@ -5949,7 +6096,6 @@ npm@^6.10.3:
|
|||
cmd-shim "^3.0.3"
|
||||
columnify "~1.5.4"
|
||||
config-chain "^1.1.12"
|
||||
debuglog "*"
|
||||
detect-indent "~5.0.0"
|
||||
detect-newline "^2.1.0"
|
||||
dezalgo "~1.0.3"
|
||||
|
@ -5964,7 +6110,6 @@ npm@^6.10.3:
|
|||
has-unicode "~2.0.1"
|
||||
hosted-git-info "^2.8.8"
|
||||
iferr "^1.0.2"
|
||||
imurmurhash "*"
|
||||
infer-owner "^1.0.4"
|
||||
inflight "~1.0.6"
|
||||
inherits "^2.0.4"
|
||||
|
@ -5983,14 +6128,8 @@ npm@^6.10.3:
|
|||
libnpx "^10.2.2"
|
||||
lock-verify "^2.1.0"
|
||||
lockfile "^1.0.4"
|
||||
lodash._baseindexof "*"
|
||||
lodash._baseuniq "~4.6.0"
|
||||
lodash._bindcallback "*"
|
||||
lodash._cacheindexof "*"
|
||||
lodash._createcache "*"
|
||||
lodash._getnative "*"
|
||||
lodash.clonedeep "~4.5.0"
|
||||
lodash.restparam "*"
|
||||
lodash.union "~4.6.0"
|
||||
lodash.uniq "~4.5.0"
|
||||
lodash.without "~4.4.0"
|
||||
|
@ -6606,6 +6745,16 @@ prettier@^2.0.5:
|
|||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
|
||||
integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
|
||||
|
||||
pretty-format@^26.0.0, pretty-format@^26.6.2:
|
||||
version "26.6.2"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93"
|
||||
integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==
|
||||
dependencies:
|
||||
"@jest/types" "^26.6.2"
|
||||
ansi-regex "^5.0.0"
|
||||
ansi-styles "^4.0.0"
|
||||
react-is "^17.0.1"
|
||||
|
||||
pretty-format@^26.2.0:
|
||||
version "26.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.2.0.tgz#83ecc8d7de676ff224225055e72bd64821cec4f1"
|
||||
|
@ -6765,6 +6914,11 @@ react-is@^16.12.0:
|
|||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.0.tgz#0f37c3613c34fe6b37cd7f763a0d6293ab15c527"
|
||||
integrity sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==
|
||||
|
||||
react-is@^17.0.1:
|
||||
version "17.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339"
|
||||
integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==
|
||||
|
||||
read-cmd-shim@^1.0.1, read-cmd-shim@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16"
|
||||
|
@ -6978,7 +7132,7 @@ regex-not@^1.0.0, regex-not@^1.0.2:
|
|||
extend-shallow "^3.0.2"
|
||||
safe-regex "^1.1.0"
|
||||
|
||||
regexpp@^3.1.0:
|
||||
regexpp@^3.0.0, regexpp@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
|
||||
integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
|
||||
|
@ -8111,6 +8265,11 @@ typedarray@^0.0.6:
|
|||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@^4.1.3:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7"
|
||||
integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.8.0.tgz#f3541ae97b2f048d7e7e3aa4f39fd8a1f5d7a805"
|
||||
|
|
Reference in a new issue