refactor: move to Typescript (#146)

* chore: add swap files to ignores

* chore: set up typescript deps

* refactor: rough conversion

* chore: linting config

* refactor: isolate untestable bits

* chore: runtime mapping

* chore: move tests
This commit is contained in:
Marc Cataford 2020-12-12 19:18:25 -05:00 committed by GitHub
parent 034f4e4089
commit 401196d62a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 683 additions and 408 deletions

View file

@ -1,6 +1,13 @@
module.exports = { module.exports = {
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
extends: [ extends: [
"@tophat/eslint-config/base", "@tophat/eslint-config/base",
"@tophat/eslint-config/jest", "@tophat/eslint-config/jest",
] "plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
settings: {
'import/resolver': { node: { extensions: ['.ts'] }}
}
} }

2
.gitignore vendored
View file

@ -102,3 +102,5 @@ dist
# TernJS port file # TernJS port file
.tern-port .tern-port
*.sw[a-z]

3
.prettierrc Normal file
View file

@ -0,0 +1,3 @@
{
"semi": false
}

View file

@ -1,5 +1,5 @@
{ {
"comments": false, "comments": false,
"ignore": ["**/*.test.js"], "ignore": ["**/*.test.js"],
"presets": [["@babel/preset-env", { "targets": { "node": 10 } }]] "presets": ["@babel/preset-typescript", ["@babel/preset-env", { "targets": { "node": 10 } }]]
} }

View file

@ -1,7 +1,7 @@
{ {
"name": "packwatch", "name": "packwatch",
"version": "0.0.0", "version": "0.0.0",
"main": "dist/index.js", "main": "dist/cli.js",
"description": "📦👀 Keep an eye on your packages' footprint", "description": "📦👀 Keep an eye on your packages' footprint",
"keywords": [ "keywords": [
"npm", "npm",
@ -19,9 +19,9 @@
"author": "Marc Cataford <c.marcandre@gmail.com>", "author": "Marc Cataford <c.marcandre@gmail.com>",
"license": "MIT", "license": "MIT",
"files": [ "files": [
"dist/**/*.js" "dist/*.ts"
], ],
"bin": "./dist/index.js", "bin": "./dist/cli.js",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/mcataford/packwatch.git" "url": "https://github.com/mcataford/packwatch.git"
@ -32,8 +32,8 @@
], ],
"scripts": { "scripts": {
"prebuild": "rimraf dist", "prebuild": "rimraf dist",
"build": "babel src -d dist", "build": "babel src/index.ts src/cli.ts -d dist --extensions .ts",
"lint": "eslint src *.js", "lint": "eslint src/**/*.ts",
"lint:fix": "yarn lint --fix", "lint:fix": "yarn lint --fix",
"test": "jest src", "test": "jest src",
"test:watch": "yarn test --watchAll", "test:watch": "yarn test --watchAll",
@ -43,7 +43,12 @@
"@babel/cli": "^7.8.4", "@babel/cli": "^7.8.4",
"@babel/core": "^7.8.6", "@babel/core": "^7.8.6",
"@babel/preset-env": "^7.8.7", "@babel/preset-env": "^7.8.7",
"@babel/preset-typescript": "^7.12.7",
"@tophat/eslint-config": "^0.7.0", "@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": "^7.0.0",
"eslint-config-prettier": "^6.10.0", "eslint-config-prettier": "^6.10.0",
"eslint-plugin-import": "^2.20.1", "eslint-plugin-import": "^2.20.1",
@ -54,6 +59,7 @@
"pre-commit": "^1.2.2", "pre-commit": "^1.2.2",
"prettier": "^2.0.5", "prettier": "^2.0.5",
"rimraf": "^3.0.2", "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
View 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
View 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)

View file

@ -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
View file

@ -0,0 +1,8 @@
export type Report = {
packageSize: string
unpackedSize?: string
packageSizeBytes?: number
unpackedSizeBytes?: number
limit?: string
limitBytes?: number
}

View file

@ -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})`,
)
}

View file

@ -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
View 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
View file

@ -103,6 +103,17 @@
"@babel/helper-replace-supers" "^7.10.4" "@babel/helper-replace-supers" "^7.10.4"
"@babel/helper-split-export-declaration" "^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": "@babel/helper-create-regexp-features-plugin@^7.10.4":
version "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" 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" 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== 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": "@babel/helper-wrap-function@^7.10.4":
version "7.10.4" version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87"
@ -517,6 +533,13 @@
dependencies: dependencies:
"@babel/helper-plugin-utils" "^7.10.4" "@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": "@babel/plugin-transform-arrow-functions@^7.10.4":
version "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" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd"
@ -754,6 +777,15 @@
dependencies: dependencies:
"@babel/helper-plugin-utils" "^7.10.4" "@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": "@babel/plugin-transform-unicode-escapes@^7.10.4":
version "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" 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" "@babel/types" "^7.4.4"
esutils "^2.0.2" 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": "@babel/runtime@^7.6.3":
version "7.8.4" version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308"
@ -1109,6 +1150,17 @@
"@types/yargs" "^15.0.0" "@types/yargs" "^15.0.0"
chalk "^4.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": "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents":
version "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" 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-coverage" "*"
"@types/istanbul-lib-report" "*" "@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": "@types/json-schema@^7.0.3":
version "7.0.4" version "7.0.4"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" 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" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.7.tgz#1628e6461ba8cc9b53196dfeaeec7b07fa6eea99"
integrity sha512-Uo4chgKbnPNlxQwoFmYIwctkQVkMMmsAoGGU4JKwLuvBefF0pCq4FybNSnfkfRCpC7ZW7kttcC/TrRtAJsvGtg== 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": "@types/normalize-package-data@^2.4.0":
version "2.4.0" version "2.4.0"
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
@ -1476,6 +1548,31 @@
dependencies: dependencies:
"@types/yargs-parser" "*" "@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": "@typescript-eslint/experimental-utils@^2.5.0":
version "2.21.0" version "2.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.21.0.tgz#71de390a3ec00b280b69138d80733406e6e86bfa" 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" "@typescript-eslint/typescript-estree" "2.21.0"
eslint-scope "^5.0.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": "@typescript-eslint/typescript-estree@2.21.0":
version "2.21.0" version "2.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.21.0.tgz#7e4be29f2e338195a2e8c818949ed0ff727cc943" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.21.0.tgz#7e4be29f2e338195a2e8c818949ed0ff727cc943"
@ -1498,6 +1618,28 @@
semver "^6.3.0" semver "^6.3.0"
tsutils "^3.17.1" 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: JSONStream@^1.0.4, JSONStream@^1.3.4, JSONStream@^1.3.5:
version "1.3.5" version "1.3.5"
resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
@ -2637,7 +2779,7 @@ debug@^3.1.0:
dependencies: dependencies:
ms "^2.1.1" ms "^2.1.1"
debuglog@*, debuglog@^1.0.1: debuglog@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= 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" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.0.0.tgz#0760059a5c287637b842bd7085311db7060e88a6"
integrity sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg== 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: dir-glob@^3.0.0, dir-glob@^3.0.1:
version "3.0.1" version "3.0.1"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" 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" esrecurse "^4.1.0"
estraverse "^4.1.1" estraverse "^4.1.1"
eslint-utils@^2.1.0: eslint-utils@^2.0.0, eslint-utils@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== 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" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== 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: eslint@^7.0.0:
version "7.6.0" version "7.6.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.6.0.tgz#522d67cfaea09724d96949c70e7a0550614d64d6" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.6.0.tgz#522d67cfaea09724d96949c70e7a0550614d64d6"
@ -3689,6 +3841,18 @@ globby@^11.0.0:
merge2 "^1.3.0" merge2 "^1.3.0"
slash "^3.0.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: got@^6.7.1:
version "6.7.1" version "6.7.1"
resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" 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" pkg-dir "^4.2.0"
resolve-cwd "^3.0.0" resolve-cwd "^3.0.0"
imurmurhash@*, imurmurhash@^0.1.4: imurmurhash@^0.1.4:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
@ -4489,6 +4653,16 @@ jest-config@^26.2.2:
micromatch "^4.0.2" micromatch "^4.0.2"
pretty-format "^26.2.0" 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: jest-diff@^26.2.0:
version "26.2.0" version "26.2.0"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.2.0.tgz#dee62c771adbb23ae585f3f1bd289a6e8ef4f298" 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" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039"
integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg== 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: jest-haste-map@^26.2.2:
version "26.2.2" version "26.2.2"
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.2.2.tgz#6d4267b1903854bfdf6a871419f35a82f03ae71e" 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: dependencies:
signal-exit "^3.0.2" 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: lodash._baseuniq@~4.6.0:
version "4.6.0" version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" 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._createset "~4.0.0"
lodash._root "~3.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: lodash._createset@~4.0.0:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY= 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: lodash._root@~3.0.0:
version "3.0.1" version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" 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" resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= 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: lodash.sortby@^4.7.0:
version "4.7.0" version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" 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" cmd-shim "^3.0.3"
columnify "~1.5.4" columnify "~1.5.4"
config-chain "^1.1.12" config-chain "^1.1.12"
debuglog "*"
detect-indent "~5.0.0" detect-indent "~5.0.0"
detect-newline "^2.1.0" detect-newline "^2.1.0"
dezalgo "~1.0.3" dezalgo "~1.0.3"
@ -5964,7 +6110,6 @@ npm@^6.10.3:
has-unicode "~2.0.1" has-unicode "~2.0.1"
hosted-git-info "^2.8.8" hosted-git-info "^2.8.8"
iferr "^1.0.2" iferr "^1.0.2"
imurmurhash "*"
infer-owner "^1.0.4" infer-owner "^1.0.4"
inflight "~1.0.6" inflight "~1.0.6"
inherits "^2.0.4" inherits "^2.0.4"
@ -5983,14 +6128,8 @@ npm@^6.10.3:
libnpx "^10.2.2" libnpx "^10.2.2"
lock-verify "^2.1.0" lock-verify "^2.1.0"
lockfile "^1.0.4" lockfile "^1.0.4"
lodash._baseindexof "*"
lodash._baseuniq "~4.6.0" lodash._baseuniq "~4.6.0"
lodash._bindcallback "*"
lodash._cacheindexof "*"
lodash._createcache "*"
lodash._getnative "*"
lodash.clonedeep "~4.5.0" lodash.clonedeep "~4.5.0"
lodash.restparam "*"
lodash.union "~4.6.0" lodash.union "~4.6.0"
lodash.uniq "~4.5.0" lodash.uniq "~4.5.0"
lodash.without "~4.4.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" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== 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: pretty-format@^26.2.0:
version "26.2.0" version "26.2.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.2.0.tgz#83ecc8d7de676ff224225055e72bd64821cec4f1" 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" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.0.tgz#0f37c3613c34fe6b37cd7f763a0d6293ab15c527"
integrity sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA== 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: read-cmd-shim@^1.0.1, read-cmd-shim@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16" 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" extend-shallow "^3.0.2"
safe-regex "^1.1.0" safe-regex "^1.1.0"
regexpp@^3.1.0: regexpp@^3.0.0, regexpp@^3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
@ -8111,6 +8265,11 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= 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: uglify-js@^3.1.4:
version "3.8.0" version "3.8.0"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.8.0.tgz#f3541ae97b2f048d7e7e3aa4f39fd8a1f5d7a805" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.8.0.tgz#f3541ae97b2f048d7e7e3aa4f39fd8a1f5d7a805"