Socket
Socket
Sign inDemoInstall

lock-verify

Package Overview
Dependencies
132
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.1 to 1.1.0

cli.js

124

index.js

@@ -1,9 +0,5 @@

#!/usr/bin/env node
'use strict'
require('@iarna/cli')(main)
.usage('lock-verify [projectPath]')
.help()
module.exports = lockVerify
const fs = require('fs')
const readFile = promisify(fs.readFile)
const path = require('path')

@@ -13,72 +9,66 @@ const npa = require('npm-package-arg')

async function main (opts, check) {
function lockVerify(check) {
if (!check) check = '.'
const pjson = await readJson(`${check}/package.json`)
let plock
try {
plock = await readJson(`${check}/npm-shrinkwrap.json`)
} catch (ex) {
plock = await readJson(`${check}/package-lock.json`)
}
let errors = false
for (let type of [['dependencies'], ['devDependencies'], ['optionalDependencies', true]]) {
const deps = pjson[type[0]]
if (!deps) continue
const isOptional = type[1]
Object.keys(deps).forEach(name => {
const spec = npa.resolve(name, deps[name])
const lock = plock.dependencies[name]
if (!lock) {
console.error('Missing:', name + '@' + deps[name])
if (!isOptional) errors = true
return
}
if (spec.registry) {
// Can't match tags to package-lock w/o network
if (spec.type === 'tag') return
if (!semver.satisfies(lock.version, spec.fetchSpec)) {
console.error("Invalid: lock file's", name + '@' + lock.version, 'does not satisfy', name + '@' + spec.fetchSpec)
errors = true
const pjson = readJson(`${check}/package.json`)
let plock = readJson(`${check}/npm-shrinkwrap.json`)
.catch(() => readJson(`${check}/package-lock.json`))
return Promise.all([pjson, plock]).then(result => {
const pjson = result[0]
const plock = result[1]
let warnings = []
let errors = []
for (let type of [['dependencies'], ['devDependencies'], ['optionalDependencies', true]]) {
const deps = pjson[type[0]]
if (!deps) continue
const isOptional = type[1]
Object.keys(deps).forEach(name => {
const spec = npa.resolve(name, deps[name])
const lock = plock.dependencies[name]
if (!lock) {
if (isOptional) {
warnings.push('Optional missing: ' + name + '@' + deps[name])
} else {
errors.push('Missing: ' + name + '@' + deps[name])
}
return
}
} else if (spec.type === 'git') {
// can't verify git w/o network
return
} else if (spec.type === 'remote') {
if (lock.version !== spec.fetchSpec) {
console.error("Invalid: lock file's", name + '@' + lock.version, 'does not satisfy', name + '@' + spec.fetchSpec)
errors = true
if (spec.registry) {
// Can't match tags to package-lock w/o network
if (spec.type === 'tag') return
if (!semver.satisfies(lock.version, spec.fetchSpec)) {
errors.push("Invalid: lock file's " + name + '@' + lock.version + ' does not satisfy ' + name + '@' + spec.fetchSpec)
return
}
} else if (spec.type === 'git') {
// can't verify git w/o network
return
} else if (spec.type === 'remote') {
if (lock.version !== spec.fetchSpec) {
errors.push("Invalid: lock file's " + name + '@' + lock.version + ' does not satisfy ' + name + '@' + spec.fetchSpec)
return
}
} else if (spec.type === 'file' || spec.type === 'directory') {
const lockSpec = npa.resolve(name, lock.version)
if (spec.fetchSpec !== lockSpec.fetchSpec) {
errors.push("Invalid: lock file's " + name + '@' + lock.version + ' does not satisfy ' + name + '@' + deps[name])
return
}
} else {
console.log(spec)
}
} else if (spec.type === 'file' || spec.type === 'directory') {
const lockSpec = npa.resolve(name, lock.version)
if (spec.fetchSpec !== lockSpec.fetchSpec) {
console.error("Invalid: lock file's", name + '@' + lock.version, 'does not satisfy', name + '@' + deps[name])
errors = true
return
}
} else {
console.log(spec)
}
})
}
if (errors) return Promise.reject('Errors found')
})
}
return Promise.resolve({status: errors.length === 0, warnings: warnings, errors: errors})
})
}
async function readJson (file) {
return JSON.parse(await readFile(file))
}
function promisify (fn) {
return function asPromised () {
return new Promise((resolve, reject) => {
const args = new Array(arguments.length + 1)
const cbIndex = arguments.length
for (var ii = 0; ii < arguments.length; ++ii) {
args[ii] = arguments[ii]
}
args[cbIndex] = (err, value) => err ? reject(err) : resolve(value)
fn.apply(this, args)
function readJson (file) {
return new Promise((resolve, reject) => {
fs.readFile(file, (err, content) => {
if (err) return reject(err)
return resolve(JSON.parse(content))
})
}
})
}
{
"name": "lock-verify",
"version": "1.0.1",
"version": "1.1.0",
"description": "Report if your package.json is out of sync with your package-lock.json.",
"bin": "index.js",
"bin": "cli.js",
"main": "index.js",
"scripts": {

@@ -13,5 +14,5 @@ "test": "echo \"Error: no test specified\" && exit 1"

"dependencies": {
"@iarna/cli": "1.1.0",
"@iarna/cli": "^1.2.0",
"npm-package-arg": "^5.1.2",
"semver": "^5.3.0"
"semver": "^5.4.1"
},

@@ -18,0 +19,0 @@ "devDependencies": {},

@@ -26,1 +26,20 @@ # lock-verify

```
## OR AS A LIBRARY
```
const lockVerify = require('lock-verify')
lockVerify(moduleDir).then(result => {
result.warnings.forEach(w => console.error('Warning:', w))
if (!result.status) {
result.errors.forEach(e => console.error(e))
process.exit(1)
}
})
```
As a library it's a function that takes the path to a module and returns a
promise that resolves to an object with `.status`, `.warnings` and `.errors`
properties. The first will be true if everything was ok (though warnings
may exist). If there's no `package.json` or no lockfile in `moduleDir` or they're
unreadable then the promise will be rejected.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc