dependencies-hierarchy
Advanced tools
Comparing version 5.0.12 to 6.0.0-0
@@ -1,2 +0,2 @@ | ||
import { Registries } from '@pnpm/types'; | ||
import { DependenciesField, Registries } from '@pnpm/types'; | ||
export declare type PackageSelector = string | { | ||
@@ -7,23 +7,35 @@ name: string; | ||
export interface PackageNode { | ||
pkg: { | ||
name: string; | ||
version: string; | ||
path: string; | ||
}; | ||
alias: string; | ||
circular?: true; | ||
dependencies?: PackageNode[]; | ||
dev?: boolean; | ||
isPeer: boolean; | ||
name: string; | ||
optional?: true; | ||
path: string; | ||
resolved?: string; | ||
searched?: true; | ||
circular?: true; | ||
saved?: false; | ||
version: string; | ||
} | ||
export declare function forPackages(packages: PackageSelector[], projectPath: string, opts?: { | ||
depth: number; | ||
only?: 'dev' | 'prod'; | ||
include?: { | ||
[dependenciesField in DependenciesField]: boolean; | ||
}; | ||
registries?: Registries; | ||
lockfileDirectory?: string; | ||
}): never[] | Promise<PackageNode[]>; | ||
}): {}; | ||
export default function (projectPath: string, opts?: { | ||
depth: number; | ||
only?: 'dev' | 'prod'; | ||
include?: { | ||
[dependenciesField in DependenciesField]: boolean; | ||
}; | ||
registries?: Registries; | ||
lockfileDirectory?: string; | ||
}): Promise<PackageNode[]>; | ||
}): Promise<DependenciesHierarchy>; | ||
export declare type DependenciesHierarchy = { | ||
dependencies?: PackageNode[]; | ||
devDependencies?: PackageNode[]; | ||
optionalDependencies?: PackageNode[]; | ||
unsavedDependencies?: PackageNode[]; | ||
}; |
181
lib/index.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const lockfile_file_1 = require("@pnpm/lockfile-file"); | ||
const lockfile_utils_1 = require("@pnpm/lockfile-utils"); | ||
const modules_yaml_1 = require("@pnpm/modules-yaml"); | ||
const read_modules_dir_1 = require("@pnpm/read-modules-dir"); | ||
const types_1 = require("@pnpm/types"); | ||
const utils_1 = require("@pnpm/utils"); | ||
@@ -16,3 +18,3 @@ const assert = require("assert"); | ||
if (!packages.length) | ||
return []; | ||
return {}; | ||
return dependenciesHierarchy(projectPath, packages, opts); | ||
@@ -31,8 +33,12 @@ } | ||
if (!lockfile) | ||
return []; | ||
const opts = Object.assign({ depth: 0, only: undefined }, maybeOpts); | ||
return {}; | ||
const opts = Object.assign({ depth: 0 }, maybeOpts); | ||
const include = maybeOpts && maybeOpts.include || { | ||
dependencies: true, | ||
devDependencies: true, | ||
optionalDependencies: true, | ||
}; | ||
const importerId = lockfile_file_1.getLockfileImporterId(lockfileDirectory, projectPath); | ||
if (!lockfile.importers[importerId]) | ||
return []; | ||
const topDeps = getFilteredDependencies(lockfile.importers[importerId], opts) || {}; | ||
return {}; | ||
const modulesDir = path.join(projectPath, 'node_modules'); | ||
@@ -42,47 +48,47 @@ const savedDeps = getAllDirectDependencies(lockfile.importers[importerId]); | ||
const unsavedDeps = allDirectDeps.filter((directDep) => !savedDeps[directDep]); | ||
if (Object.keys(topDeps).length === 0 && unsavedDeps.length === 0) | ||
return []; | ||
const getChildrenTree = getTree.bind(null, { | ||
currentDepth: 1, | ||
includeOptionalDependencies: include.optionalDependencies === true, | ||
maxDepth: opts.depth, | ||
modulesDir, | ||
prod: opts.only === 'prod', | ||
registries, | ||
searched, | ||
}, lockfile.packages); | ||
const result = []; | ||
Object.keys(topDeps).forEach((depName) => { | ||
const pkgPath = dependency_path_1.refToAbsolute(topDeps[depName], depName, registries); | ||
const pkg = { | ||
name: depName, | ||
path: pkgPath && path.join(modulesDir, `.${pkgPath}`) || path.join(modulesDir, '..', topDeps[depName].substr(5)), | ||
version: topDeps[depName], | ||
}; | ||
let newEntry = null; | ||
const matchedSearched = searched.length && matches(searched, pkg); | ||
if (pkgPath === null) { | ||
if (searched.length && !matchedSearched) | ||
return; | ||
newEntry = { pkg }; | ||
} | ||
else { | ||
const relativeId = dependency_path_1.refToRelative(topDeps[depName], depName); | ||
const dependencies = getChildrenTree([relativeId], relativeId); | ||
if (dependencies.length) { | ||
newEntry = { | ||
dependencies, | ||
pkg, | ||
}; | ||
const result = {}; | ||
for (const dependenciesField of types_1.DEPENDENCIES_FIELDS.sort().filter(dependenciedField => include[dependenciedField])) { | ||
const topDeps = lockfile.importers[importerId][dependenciesField] || {}; | ||
result[dependenciesField] = []; | ||
Object.keys(topDeps).forEach((alias) => { | ||
const { packageInfo, packageAbsolutePath } = getPkgInfo({ | ||
alias, | ||
modulesDir, | ||
packages: lockfile.packages || {}, | ||
ref: topDeps[alias], | ||
registries, | ||
}); | ||
let newEntry = null; | ||
const matchedSearched = searched.length && matches(searched, packageInfo); | ||
if (packageAbsolutePath === null) { | ||
if (searched.length && !matchedSearched) | ||
return; | ||
newEntry = packageInfo; | ||
} | ||
else if (!searched.length || matches(searched, pkg)) { | ||
newEntry = { pkg }; | ||
else { | ||
const relativeId = dependency_path_1.refToRelative(topDeps[alias], alias); | ||
const dependencies = getChildrenTree([relativeId], relativeId); | ||
if (dependencies.length) { | ||
newEntry = Object.assign({}, packageInfo, { dependencies }); | ||
} | ||
else if (!searched.length || matches(searched, packageInfo)) { | ||
newEntry = packageInfo; | ||
} | ||
} | ||
} | ||
if (newEntry) { | ||
if (matchedSearched) { | ||
newEntry.searched = true; | ||
if (newEntry) { | ||
if (matchedSearched) { | ||
newEntry.searched = true; | ||
} | ||
result[dependenciesField].push(newEntry); | ||
} | ||
result.push(newEntry); | ||
} | ||
}); | ||
}); | ||
} | ||
await Promise.all(unsavedDeps.map(async (unsavedDep) => { | ||
@@ -101,2 +107,4 @@ let pkgPath = path.join(modulesDir, unsavedDep); | ||
const pkg = { | ||
alias: unsavedDep, | ||
isPeer: false, | ||
name: unsavedDep, | ||
@@ -109,23 +117,11 @@ path: pkgPath, | ||
return; | ||
const newEntry = { | ||
pkg, | ||
saved: false, | ||
}; | ||
const newEntry = pkg; | ||
if (matchedSearched) { | ||
newEntry.searched = true; | ||
} | ||
result.push(newEntry); | ||
result.unsavedDependencies = result.unsavedDependencies || []; | ||
result.unsavedDependencies.push(newEntry); | ||
})); | ||
return result; | ||
} | ||
function getFilteredDependencies(lockfileImporter, opts) { | ||
switch (opts.only) { | ||
case 'prod': | ||
return lockfileImporter.dependencies; | ||
case 'dev': | ||
return lockfileImporter.devDependencies; | ||
default: | ||
return getAllDirectDependencies(lockfileImporter); | ||
} | ||
} | ||
function getAllDirectDependencies(lockfileImporter) { | ||
@@ -137,3 +133,3 @@ return Object.assign({}, lockfileImporter.dependencies, lockfileImporter.devDependencies, lockfileImporter.optionalDependencies); | ||
return []; | ||
const deps = opts.prod | ||
const deps = opts.includeOptionalDependencies === false | ||
? packages[parentId].dependencies | ||
@@ -144,29 +140,29 @@ : Object.assign({}, packages[parentId].dependencies, packages[parentId].optionalDependencies); | ||
const getChildrenTree = getTree.bind(null, Object.assign({}, opts, { currentDepth: opts.currentDepth + 1 }), packages); | ||
const peers = new Set(Object.keys(packages[parentId].peerDependencies || {})); | ||
const result = []; | ||
Object.keys(deps).forEach((depName) => { | ||
const pkgPath = dependency_path_1.refToAbsolute(deps[depName], depName, opts.registries); | ||
const pkg = { | ||
name: depName, | ||
path: pkgPath && path.join(opts.modulesDir, `.${pkgPath}`) || path.join(opts.modulesDir, '..', deps[depName].substr(5)), | ||
version: deps[depName], | ||
}; | ||
Object.keys(deps).forEach((alias) => { | ||
const { packageInfo, packageAbsolutePath } = getPkgInfo({ | ||
alias, | ||
modulesDir: opts.modulesDir, | ||
packages, | ||
peers, | ||
ref: deps[alias], | ||
registries: opts.registries, | ||
}); | ||
let circular; | ||
const matchedSearched = opts.searched.length && matches(opts.searched, pkg); | ||
const matchedSearched = opts.searched.length && matches(opts.searched, packageInfo); | ||
let newEntry = null; | ||
if (pkgPath === null) { | ||
if (packageAbsolutePath === null) { | ||
circular = false; | ||
newEntry = { pkg }; | ||
newEntry = packageInfo; | ||
} | ||
else { | ||
const relativeId = dependency_path_1.refToRelative(deps[depName], depName); // we know for sure that relative is not null if pkgPath is not null | ||
const relativeId = dependency_path_1.refToRelative(deps[alias], alias); // we know for sure that relative is not null if pkgPath is not null | ||
circular = keypath.includes(relativeId); | ||
const dependencies = circular ? [] : getChildrenTree(keypath.concat([relativeId]), relativeId); | ||
if (dependencies.length) { | ||
newEntry = { | ||
dependencies, | ||
pkg, | ||
}; | ||
newEntry = Object.assign({}, packageInfo, { dependencies }); | ||
} | ||
else if (!opts.searched.length || matchedSearched) { | ||
newEntry = { pkg }; | ||
newEntry = packageInfo; | ||
} | ||
@@ -186,2 +182,43 @@ } | ||
} | ||
function getPkgInfo(opts) { | ||
let name; | ||
let version; | ||
let resolved = undefined; | ||
let dev = undefined; | ||
let optional = undefined; | ||
const relDepPath = dependency_path_1.refToRelative(opts.ref, opts.alias); | ||
if (relDepPath) { | ||
const parsed = lockfile_utils_1.nameVerFromPkgSnapshot(relDepPath, opts.packages[relDepPath]); | ||
name = parsed.name; | ||
version = parsed.version; | ||
resolved = lockfile_utils_1.pkgSnapshotToResolution(relDepPath, opts.packages[relDepPath], opts.registries)['tarball']; | ||
dev = opts.packages[relDepPath].dev; | ||
optional = opts.packages[relDepPath].optional; | ||
} | ||
else { | ||
name = opts.alias; | ||
version = opts.ref; | ||
} | ||
const packageAbsolutePath = dependency_path_1.refToAbsolute(opts.ref, opts.alias, opts.registries); | ||
const packageInfo = { | ||
alias: opts.alias, | ||
isPeer: Boolean(opts.peers && opts.peers.has(opts.alias)), | ||
name, | ||
path: packageAbsolutePath && path.join(opts.modulesDir, `.${packageAbsolutePath}`) || path.join(opts.modulesDir, '..', opts.ref.substr(5)), | ||
version, | ||
}; | ||
if (resolved) { | ||
packageInfo['resolved'] = resolved; | ||
} | ||
if (optional === true) { | ||
packageInfo['optional'] = true; | ||
} | ||
if (typeof dev === 'boolean') { | ||
packageInfo['dev'] = dev; | ||
} | ||
return { | ||
packageAbsolutePath, | ||
packageInfo, | ||
}; | ||
} | ||
function matches(searched, pkg) { | ||
@@ -188,0 +225,0 @@ return searched.some((searchedPkg) => { |
{ | ||
"name": "dependencies-hierarchy", | ||
"version": "5.0.12", | ||
"version": "6.0.0-0", | ||
"description": "Creates a dependencies hierarchy for a symlinked `node_modules`", | ||
@@ -40,2 +40,3 @@ "main": "lib/index.js", | ||
"@pnpm/lockfile-file": "1.1.1", | ||
"@pnpm/lockfile-utils": "1.0.10", | ||
"@pnpm/modules-yaml": "3.0.3", | ||
@@ -42,0 +43,0 @@ "@pnpm/read-modules-dir": "2.0.1", |
@@ -17,78 +17,4 @@ # dependencies-hierarchy | ||
## Usage | ||
```js | ||
'use strict' | ||
const hierarchyForPackages = require('dependencies-hierarchy').forPackages | ||
hierarchyForPackages(['graceful-fs', {name: 'pify', range: '2'}], __dirname, {depth: 2}) | ||
.then(tree => { | ||
console.log(JSON.stringify(tree, null, 2)) | ||
//> [ | ||
// { | ||
// "dependencies": [ | ||
// { | ||
// "dependencies": [ | ||
// { | ||
// "pkg": { | ||
// "name": "graceful-fs", | ||
// "path": "/home/zoltan/src/pnpm/pnpm/packages/dependencies-hierarchy/example/node_modules/.registry.npmjs.org/graceful-fs/4.1.11", | ||
// "version": "4.1.11" | ||
// }, | ||
// "searched": true | ||
// }, | ||
// { | ||
// "pkg": { | ||
// "name": "pify", | ||
// "path": "/home/zoltan/src/pnpm/pnpm/packages/dependencies-hierarchy/example/node_modules/.registry.npmjs.org/pify/2.3.0", | ||
// "version": "2.3.0" | ||
// }, | ||
// "searched": true | ||
// } | ||
// ], | ||
// "pkg": { | ||
// "name": "write-json-file", | ||
// "path": "/home/zoltan/src/pnpm/pnpm/packages/dependencies-hierarchy/example/node_modules/.registry.npmjs.org/write-json-file/2.2.0", | ||
// "version": "2.2.0" | ||
// } | ||
// } | ||
// ], | ||
// "pkg": { | ||
// "name": "write-pkg", | ||
// "path": "/home/zoltan/src/pnpm/pnpm/packages/dependencies-hierarchy/example/node_modules/.registry.npmjs.org/write-pkg/3.1.0", | ||
// "version": "3.1.0" | ||
// } | ||
// } | ||
// ] | ||
}) | ||
``` | ||
## API | ||
### default: `dependenciesHierarchy(projectPath, [opts]): Promise<Hierarchy>` | ||
Creates a dependency tree for a project's `node_modules`. | ||
#### Arguments: | ||
- `projectPath` - _String_ - The path to the project. | ||
- `[opts.depth]` - _Number_ - 0 by default. How deep should the `node_modules` be analyzed. | ||
- `[opts.only]` - _'dev' | 'prod'_ - Optional. If set to `dev`, then only packages from `devDependencies` are analyzed. | ||
If set to `prod`, then only packages from `dependencies` are analyzed. | ||
### `forPackages(packageSelectors, projectPath, [opts]): Promise<Hierarchy>` | ||
Creates a dependency tree for a project's `node_modules`. Limits the results to only the paths to the packages named. | ||
#### Arguments: | ||
- `packageSelectors` - _(string | {name: string, version: string})\[]_ - An array that consist of package names or package names and version ranges. | ||
E.g. `['foo', {name: 'bar', version: '^2.0.0'}]`. | ||
- `projectPath` - _String_ - The path to the project | ||
- `[opts.depth]` - _Number_ - 0 by default. How deep should the `node_modules` be analyzed. | ||
- `[opts.only]` - _'dev' | 'prod'_ - Optional. If set to `dev`, then only packages from `devDependencies` are analyzed. | ||
If set to `prod`, then only packages from `dependencies` are analyzed. | ||
## License | ||
MIT © [Zoltan Kochan](https://www.kochan.io/) |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
265
13764
10
2
20
+ Added@pnpm/lockfile-utils@1.0.10
+ Added@pnpm/lockfile-utils@1.0.10(transitive)
+ Added@pnpm/resolver-base@3.1.2(transitive)
+ Addedget-npm-tarball-url@2.0.1(transitive)