Skip to content

Commit

Permalink
Use files-property in package.json to be more precise about the size...
Browse files Browse the repository at this point in the history
  • Loading branch information
nknapp committed May 5, 2017
1 parent 184d2d6 commit 4773afa
Show file tree
Hide file tree
Showing 19 changed files with 419 additions and 16 deletions.
2 changes: 1 addition & 1 deletion bin/analyze-module-size.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env node

var {analyze} = require('../src/index')
analyze(process.cwd())
analyze(process.cwd(), {depth: process.argv[2]})
.then(
(output) => process.stdout.write(output),
(err) => process.stderr.write(err.stack + '\n')
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"chalk": "^1.1.3",
"deep-aplus": "^1.0.4",
"glob": "^7.1.1",
"globby": "^6.1.0",
"pify": "^2.3.0"
},
"devDependencies": {
Expand All @@ -51,6 +52,7 @@
"istanbul": "^0.4.5",
"lodash.sortby": "^4.7.0",
"mocha": "^3.2.0",
"mock-fs": "^4.3.0",
"thoughtful-release": "^0.3.1",
"trace-and-clarify-if-possible": "^1.0.0"
},
Expand All @@ -60,6 +62,7 @@
]
},
"files": [
"bin",
"src"
],
"keywords": []
Expand Down
2 changes: 1 addition & 1 deletion src/Package.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class Package {
*/
static loadFrom (packageJsonPath) {
var json = readFile(packageJsonPath).then(JSON.parse)
var stats = PackageStats.loadFrom(packageJsonPath)
var stats = PackageStats.loadFrom(packageJsonPath, json)
return deep({json, stats})
.then(({json, stats}) => new Package(json, stats))
}
Expand Down
21 changes: 13 additions & 8 deletions src/PackageStats.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const deep = require('deep-aplus')(Promise)
const pify = require('pify')
const fs = require('fs')
const stat = pify(fs.stat)
const glob = pify(require('glob'))
const {validFiles} = require('./validFiles')

/**
* Computes and aggregates a number of statistics from a package directory
Expand Down Expand Up @@ -61,15 +61,20 @@ class PackageStats {
}

/**
* Create PackageStats from the location of a package.json file
*
* @param packageJsonPath
* @return {Promise<PackageStats>}
* @param packageJsonPath path to the package.json file
* @param {Promise<object>|object=} packageJson the parse package.json file,
* either directly or as Promise
* @return {Promise<PackageStats>} a promise for the PackageStats object
*/
static loadFrom (packageJsonPath) {
var directory = path.dirname(packageJsonPath)
return glob('**', {dot: true, cwd: directory, mark: true, ignore: 'node_modules/**'})
// Add the directory itself
.then(files => ['./'].concat(files))
static loadFrom (packageJsonPath, packageJson = {}) {
const directory = path.dirname(packageJsonPath)

return Promise.resolve(packageJson)
.then((packageJson) => validFiles(directory, packageJson))
// Add the directory itself
.then(files => files.map((file) => path.normalize(file)))
// Gather stats
.then(files => files.map(file => ({file: path.join(directory, file), stat: stat(path.join(directory, file))})))
// Wait for promises
Expand Down
22 changes: 17 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,36 @@ const archy = require('archy')
const chalk = require('chalk')
const path = require('path')

function analyze (cwd) {
/**
*
* @param cwd
* @param options
* @param {number} options.depth The number of levels to display in the tree-view
*/
function analyze (cwd, options) {
return DependencyTree.loadFrom(path.join(cwd, 'package.json'))
.then(function (tree) {
return archy({
label: `total-size: ${tree.rootPackage.totalStats().totalBlockSize() / 1024}k`,
nodes: toArchy(tree.prod)
label: `size: ${tree.rootPackage.stats.totalBlockSize() / 1024}k... with-dependencies: ${tree.rootPackage.totalStats().totalBlockSize() / 1024}k`,
nodes: toArchy(tree.prod, options && options.depth)
})
})
}

function toArchy (pkgs) {
/**
*
* @param pkgs
* @param {number=} depth
*/
function toArchy (pkgs, depth) {
if (depth <= 0) return []
const result = pkgs.map(pkg => {
const blockSize = pkg.totalStats().totalBlockSize()
const dependencyCount = pkg.totalDependencies()
return {
label: `${pkg.packageJson._id}, ${chalk.red(blockSize / 1024 + 'k')}, ${dependencyCount} deps`,
size: blockSize,
nodes: toArchy(pkg.dependencies)
nodes: toArchy(pkg.dependencies, depth && depth - 1)
}
})
return sortby(result, (node) => {
Expand Down
93 changes: 93 additions & 0 deletions src/validFiles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
var globby = require('globby')
var deep = require('deep-aplus')(Promise)

/**
* List of ignored files (from https://docs.npmjs.com/files/package.json#files)
* @type {string[]}
*/
var alwaysIgnored = [
'.git',
'CVS',
'.svn',
'.hg',
'.lock-wscript',
'.wafpickle-*',
'.*.swp',
'.DS_Store',
'._*',
'npm-debug.log',
'.npmrc',
'node_modules',
'config.gypi',
'*.orig'
]

var alwaysIncluded = [
'package.json'
]

var alwaysIncludedIgnoreCase = [
'README', 'README.*',
'CHANGES', 'CHANGES.*',
'CHANGELOG', 'CHANGELOG.*',
'HISTORY', 'HISTORY.*',
'LICENSE', 'LICENSE.*',
'LICENCE', 'LICENCE.*',
'NOTICE', 'NOTICE.*'
]

/**
*
* @param {string} cwd the projects basedir
* @param {{files: string[]} packageJson the parsed package.json
* @param {string[]} npmIgnore non-comment lines of the npm-ignore file
* @returns {Promise.<string[]>} a promise for a list of valid files in the project
*/
function validFiles (cwd, packageJson, npmIgnore = []) {
var ignored = alwaysIgnored.concat(npmIgnore).map(withChildren)

var globs
if (packageJson.files) {
globs = packageJson.files
.map((file) => file.replace(/\/?$/, '{,/**}'))
.concat(alwaysIncluded)
} else {
globs = '**'
}

return deep({
withCase: globby(globs, {nocase: false, ignore: ignored, cwd, mark: true}),
ignoreCase: globby(alwaysIncludedIgnoreCase, {nocase: true, ignore: ignored, cwd, mark: true})
})
// Join
.then(({withCase, ignoreCase}) => withCase.concat(ignoreCase, '/'))
// remove duplicates
.then(files => Array.from(new Set(files)))
}

/**
* Returns a glob the matches the file itself and its children (if it is an directory)
* @param file
*/
function withChildren (file) {
return file.replace(/\/?$/, '{,/**}')
}

/**
* Returns an array of globs that match a file, its children (if it is an directory) and its
* parent directories (recursively)
* @param file
*/
function withParentsAndChildren (file) {
// Determine globs for parents matching
const globs = file.replace(/\/$/, '').match(/.*?\//g)
.map((item, index, array) => array.slice(0, index + 1).join(''))
// Add pattern to match children
globs.push(withChildren(file))
return globs
}

module.exports = {
validFiles,
withParentsAndChildren
}
16 changes: 16 additions & 0 deletions test/Package-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ describe('The Package-class:', function () {
])
})
})

it('should respect the files property in the package.json', function () {
return Package.loadFrom('test/fixtures/project3/package.json')
.then((pkg) => {
expect(pkg.packageJson).to.deep.equal(require('./fixtures/project3/package.json'))
expect(pkg.stats.files.map((f) => f.file).sort()).to.deep.equal([
'test/fixtures/project3/',
'test/fixtures/project3/LICENSE.md',
'test/fixtures/project3/README',
'test/fixtures/project3/dir/',
'test/fixtures/project3/dir/file2.txt',
'test/fixtures/project3/file3.txt',
'test/fixtures/project3/package.json'
])
})
})
})

it('should contain "/" as location by default (because this is the base package.json then', function () {
Expand Down
16 changes: 16 additions & 0 deletions test/PackageStats-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ describe('The PackageStats-class', function () {
})
})

it('should filter files via the provided in files-property', function () {
return PackageStats.loadFrom('test/fixtures/project3/package.json', {files: ['dir/', 'file3.txt']})
.then((packageStats) => {
expect(packageStats.directory).to.equal('test/fixtures/project3')
expect(sortedNameAndSize(packageStats.files)).to.deep.equal([
f('test/fixtures/project3/'),
f('test/fixtures/project3/LICENSE.md'),
f('test/fixtures/project3/README'),
f('test/fixtures/project3/dir/'),
f('test/fixtures/project3/dir/file2.txt'),
f('test/fixtures/project3/file3.txt'),
f('test/fixtures/project3/package.json')
])
})
})

it('should compute the byte-size of all the files in a directory', function () {
return PackageStats.loadFrom('test/fixtures/project1/package.json')
.then((packageStats) => {
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/moduleWithDeps.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
total-size: 56k
size: 24k... with-dependencies: 56k
├─┬ dep1@1.0.0, 16k, 1 deps
│ └── dep1a@1.0.0, 8k, 0 deps
└─┬ dep2@1.0.0, 16k, 1 deps
Expand Down
Empty file.
1 change: 1 addition & 0 deletions test/fixtures/project3/README
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a readme
1 change: 1 addition & 0 deletions test/fixtures/project3/dir/file2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a
1 change: 1 addition & 0 deletions test/fixtures/project3/dir2/file2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a
1 change: 1 addition & 0 deletions test/fixtures/project3/file3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ab
100 changes: 100 additions & 0 deletions test/fixtures/project3/file5000.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
0123456789012345678901234567890123456789012345678
1 change: 1 addition & 0 deletions test/fixtures/project3/file6.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
abcef

0 comments on commit 4773afa

Please sign in to comment.