/home/lnzliplg/www/npm-logical-tree.tar
index.js000064400000011467151730726210006226 0ustar00'use strict'

let path

class LogicalTree {
  constructor (name, address, opts) {
    this.name = name
    this.version = opts.version
    this.address = address || ''
    this.optional = !!opts.optional
    this.dev = !!opts.dev
    this.bundled = !!opts.bundled
    this.resolved = opts.resolved
    this.integrity = opts.integrity
    this.dependencies = new Map()
    this.requiredBy = new Set()
  }

  get isRoot () { return !this.requiredBy.size }

  addDep (dep) {
    this.dependencies.set(dep.name, dep)
    dep.requiredBy.add(this)
    return this
  }

  delDep (dep) {
    this.dependencies.delete(dep.name)
    dep.requiredBy.delete(this)
    return this
  }

  getDep (name) {
    return this.dependencies.get(name)
  }

  path (prefix) {
    if (this.isRoot) {
      // The address of the root is the prefix itself.
      return prefix || ''
    } else {
      if (!path) { path = require('path') }
      return path.join(
        prefix || '',
        'node_modules',
        this.address.replace(/:/g, '/node_modules/')
      )
    }
  }

  // This finds cycles _from_ a given node: if some deeper dep has
  // its own cycle, but that cycle does not refer to this node,
  // it will return false.
  hasCycle (_seen, _from) {
    if (!_seen) { _seen = new Set() }
    if (!_from) { _from = this }
    for (let dep of this.dependencies.values()) {
      if (_seen.has(dep)) { continue }
      _seen.add(dep)
      if (dep === _from || dep.hasCycle(_seen, _from)) {
        return true
      }
    }
    return false
  }

  forEachAsync (fn, opts, _pending) {
    if (!opts) { opts = _pending || {} }
    if (!_pending) { _pending = new Map() }
    const P = opts.Promise || Promise
    if (_pending.has(this)) {
      return P.resolve(this.hasCycle() || _pending.get(this))
    }
    const pending = P.resolve().then(() => {
      return fn(this, () => {
        return promiseMap(
          this.dependencies.values(),
          dep => dep.forEachAsync(fn, opts, _pending),
          opts
        )
      })
    })
    _pending.set(this, pending)
    return pending
  }

  forEach (fn, _seen) {
    if (!_seen) { _seen = new Set() }
    if (_seen.has(this)) { return }
    _seen.add(this)
    fn(this, () => {
      for (let dep of this.dependencies.values()) {
        dep.forEach(fn, _seen)
      }
    })
  }
}

module.exports = lockTree
function lockTree (pkg, pkgLock, opts) {
  const tree = makeNode(pkg.name, null, pkg)
  const allDeps = new Map()
  Array.from(
    new Set(Object.keys(pkg.devDependencies || {})
    .concat(Object.keys(pkg.optionalDependencies || {}))
    .concat(Object.keys(pkg.dependencies || {})))
  ).forEach(name => {
    let dep = allDeps.get(name)
    if (!dep) {
      const depNode = (pkgLock.dependencies || {})[name]
      dep = makeNode(name, name, depNode)
    }
    addChild(dep, tree, allDeps, pkgLock)
  })
  return tree
}

module.exports.node = makeNode
function makeNode (name, address, opts) {
  return new LogicalTree(name, address, opts || {})
}

function addChild (dep, tree, allDeps, pkgLock) {
  tree.addDep(dep)
  allDeps.set(dep.address, dep)
  const addr = dep.address
  const lockNode = atAddr(pkgLock, addr)
  Object.keys(lockNode.requires || {}).forEach(name => {
    const tdepAddr = reqAddr(pkgLock, name, addr)
    let tdep = allDeps.get(tdepAddr)
    if (!tdep) {
      tdep = makeNode(name, tdepAddr, atAddr(pkgLock, tdepAddr))
      addChild(tdep, dep, allDeps, pkgLock)
    } else {
      dep.addDep(tdep)
    }
  })
}

module.exports._reqAddr = reqAddr
function reqAddr (pkgLock, name, fromAddr) {
  const lockNode = atAddr(pkgLock, fromAddr)
  const child = (lockNode.dependencies || {})[name]
  if (child) {
    return `${fromAddr}:${name}`
  } else {
    const parts = fromAddr.split(':')
    while (parts.length) {
      parts.pop()
      const joined = parts.join(':')
      const parent = atAddr(pkgLock, joined)
      if (parent) {
        const child = (parent.dependencies || {})[name]
        if (child) {
          return `${joined}${parts.length ? ':' : ''}${name}`
        }
      }
    }
    const err = new Error(`${name} not accessible from ${fromAddr}`)
    err.pkgLock = pkgLock
    err.target = name
    err.from = fromAddr
    throw err
  }
}

module.exports._atAddr = atAddr
function atAddr (pkgLock, addr) {
  if (!addr.length) { return pkgLock }
  const parts = addr.split(':')
  return parts.reduce((acc, next) => {
    return acc && (acc.dependencies || {})[next]
  }, pkgLock)
}

function promiseMap (arr, fn, opts, _index) {
  _index = _index || 0
  const P = (opts && opts.Promise) || Promise
  if (P.map) {
    return P.map(arr, fn, opts)
  } else {
    if (!(arr instanceof Array)) {
      arr = Array.from(arr)
    }
    if (_index >= arr.length) {
      return P.resolve()
    } else {
      return P.resolve(fn(arr[_index], _index, arr))
      .then(() => promiseMap(arr, fn, opts, _index + 1))
    }
  }
}
README.md000064400000010723151730726210006032 0ustar00# npm-logical-tree [![npm version](https://img.shields.io/npm/v/npm-logical-tree.svg)](https://npm.im/npm-logical-tree) [![license](https://img.shields.io/npm/l/npm-logical-tree.svg)](https://npm.im/npm-logical-tree) [![Travis](https://img.shields.io/travis/npm/logical-tree.svg)](https://travis-ci.org/npm/logical-tree) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/npm/logical-tree?svg=true)](https://ci.appveyor.com/project/npm/logical-tree) [![Coverage Status](https://coveralls.io/repos/github/npm/logical-tree/badge.svg?branch=latest)](https://coveralls.io/github/npm/logical-tree?branch=latest)

[`npm-logical-tree`](https://github.com/npm/npm-logical-tree) is a Node.js
library that takes the contents of a `package.json` and `package-lock.json` (or
`npm-shrinkwrap.json`) and returns a nested tree data structure representing the
logical relationships between the different dependencies.

## Install

`$ npm install npm-logical-tree`

## Table of Contents

* [Example](#example)
* [Contributing](#contributing)
* [API](#api)
  * [`logicalTree`](#logical-tree)
  * [`logicalTree.node`](#make-node)
  * [`tree.isRoot`](#is-root)
  * [`tree.addDep`](#add-dep)
  * [`tree.delDep`](#del-dep)
  * [`tree.getDep`](#get-dep)
  * [`tree.path`](#path)
  * [`tree.hasCycle`](#has-cycle)
  * [`tree.forEach`](#for-each)
  * [`tree.forEachAsync`](#for-each-async)

### Example

```javascript
const fs = require('fs')
const logicalTree = require('npm-logical-tree')

const pkg = require('./package.json')
const pkgLock = require('./package-lock.json')

logicalTree(pkg, pkgLock)
// returns:
LogicalTree {
  name: 'npm-logical-tree',
  version: '1.0.0',
  address: null,
  optional: false,
  dev: false,
  bundled: false,
  resolved: undefined,
  integrity: undefined,
  requiredBy: Set { },
  dependencies:
   Map {
     'foo' => LogicalTree {
       name: 'foo',
       version: '1.2.3',
       address: 'foo',
       optional: false,
       dev: true,
       bundled: false,
       resolved: 'https://registry.npmjs.org/foo/-/foo-1.2.3.tgz',
       integrity: 'sha1-rYUK/p261/SXByi0suR/7Rw4chw=',
       dependencies: Map { ... },
       requiredBy: Set { ... },
     },
     ...
  }
}
```

### Contributing

The npm team enthusiastically welcomes contributions and project participation!
There's a bunch of things you can do if you want to contribute! The [Contributor
Guide](CONTRIBUTING.md) has all the information you need for everything from
reporting bugs to contributing entire new features. Please don't hesitate to
jump in if you'd like to, or even ask us questions if something isn't clear.

All participants and maintainers in this project are expected to follow [Code of
Conduct](CODE_OF_CONDUCT.md), and just generally be excellent to each other.

Please refer to the [Changelog](CHANGELOG.md) for project history details, too.

Happy hacking!

### API

#### <a name="logical-tree"></a> `> logicalTree(pkg, lock) -> LogicalTree`

Calculates a logical tree based on a matching `package.json` and
`package-lock.json` pair. A "logical tree" is a fully-nested dependency graph
for an npm package, as opposed to a physical tree which might be flattened.

`logical-tree` will represent deduplicated/flattened nodes using the same object
throughout the tree, so duplication can be checked by object identity.

##### Example

```javascript
const pkg = require('./package.json')
const pkgLock = require('./package-lock.json')

logicalTree(pkg, pkgLock)
// returns:
LogicalTree {
  name: 'npm-logical-tree',
  version: '1.0.0',
  address: null,
  optional: false,
  dev: false,
  bundled: false,
  resolved: undefined,
  integrity: undefined,
  requiredBy: Set { },
  dependencies:
   Map {
     'foo' => LogicalTree {
       name: 'foo',
       version: '1.2.3',
       address: 'foo',
       optional: false,
       dev: true,
       bundled: false,
       resolved: 'https://registry.npmjs.org/foo/-/foo-1.2.3.tgz',
       integrity: 'sha1-rYUK/p261/SXByi0suR/7Rw4chw=',
       requiredBy: Set { ... },
       dependencies: Map { ... }
     },
     ...
  }
}
```

#### <a name="make-node"></a> `> logicalTree.node(name, [address, [opts]]) -> LogicalTree`

Manually creates a new LogicalTree node.

##### Options

* `opts.version` - version of the node.
* `opts.optional` - is this node an optionalDep?
* `opts.dev` - is this node a devDep?
* `opts.bundled` - is this bundled?
* `opts.resolved` - resolved address.
* `opts.integrity` - SRI string.

##### Example
```javascript
logicalTree.node('hello', 'subpath:to:@foo/bar', {dev: true})
```
CHANGELOG.md000064400000002306151730726210006362 0ustar00# Change Log

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

<a name="1.2.1"></a>
## [1.2.1](https://github.com/npm/logical-tree/compare/v1.2.0...v1.2.1) (2018-01-19)


### Bug Fixes

* **requires:** stop requiring version match -- only what require would pick up ([6388fbd](https://github.com/npm/logical-tree/commit/6388fbd))



<a name="1.2.0"></a>
# [1.2.0](https://github.com/npm/logical-tree/compare/v1.1.0...v1.2.0) (2017-10-13)


### Bug Fixes

* **json:** fix repository url ([e51448a](https://github.com/npm/logical-tree/commit/e51448a))


### Features

* **api:** additional utility functions for dealing with trees ([23f6e69](https://github.com/npm/logical-tree/commit/23f6e69))



<a name="1.1.0"></a>
# [1.1.0](https://github.com/npm/npm-logical-tree/compare/v1.0.0...v1.1.0) (2017-10-11)


### Features

* **requiredBy:** add requiredBy field to nodes ([c4056fb](https://github.com/npm/npm-logical-tree/commit/c4056fb))



<a name="1.0.0"></a>
# 1.0.0 (2017-10-07)


### Features

* **api:** Initial Commitâ„¢ ([1025259](https://github.com/npm/npm-logical-tree/commit/1025259))
LICENSE.md000064400000001363151730726210006157 0ustar00ISC License

Copyright (c) npm, Inc.

Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE COPYRIGHT HOLDER DISCLAIMS
ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.
package.json000064400000004465151730726210007047 0ustar00{
  "_from": "npm-logical-tree@^1.2.1",
  "_id": "npm-logical-tree@1.2.1",
  "_inBundle": false,
  "_integrity": "sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg==",
  "_location": "/npm-logical-tree",
  "_phantomChildren": {},
  "_requested": {
    "type": "range",
    "registry": true,
    "raw": "npm-logical-tree@^1.2.1",
    "name": "npm-logical-tree",
    "escapedName": "npm-logical-tree",
    "rawSpec": "^1.2.1",
    "saveSpec": null,
    "fetchSpec": "^1.2.1"
  },
  "_requiredBy": [
    "/libcipm"
  ],
  "_resolved": "https://registry.npmjs.org/npm-logical-tree/-/npm-logical-tree-1.2.1.tgz",
  "_shasum": "44610141ca24664cad35d1e607176193fd8f5b88",
  "_spec": "npm-logical-tree@^1.2.1",
  "_where": "/Users/rebecca/code/npm/node_modules/libcipm",
  "author": {
    "name": "Kat Marchán",
    "email": "kzm@sykosomatic.org"
  },
  "bugs": {
    "url": "https://github.com/npm/logical-tree/issues"
  },
  "bundleDependencies": false,
  "config": {
    "nyc": {
      "exclude": [
        "node_modules/**",
        "test/**"
      ]
    }
  },
  "contributors": [
    {
      "name": "Rebecca Turner",
      "email": "me@re-becca.org"
    }
  ],
  "deprecated": false,
  "description": "Calculate 'logical' trees from a package.json + package-lock",
  "devDependencies": {
    "bluebird": "^3.5.1",
    "nyc": "^11.1.0",
    "standard": "^10.0.2",
    "standard-version": "^4.2.0",
    "tap": "^10.7.0",
    "weallbehave": "^1.2.0",
    "weallcontribute": "^1.0.8"
  },
  "files": [
    "*.js"
  ],
  "homepage": "https://github.com/npm/logical-tree#readme",
  "keywords": [
    "npm",
    "package manager"
  ],
  "license": "ISC",
  "main": "index.js",
  "name": "npm-logical-tree",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/npm/logical-tree.git"
  },
  "scripts": {
    "postrelease": "npm publish && git push --follow-tags",
    "prerelease": "npm t",
    "pretest": "standard lib test *.js",
    "release": "standard-version -s",
    "test": "nyc --all -- tap -J test/*.js",
    "update-coc": "weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'",
    "update-contrib": "weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"
  },
  "version": "1.2.1"
}