Skip to content

Commit

Permalink
feat: add support for different type of dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
Mila Votradovec authored and lili2311 committed Aug 17, 2018
1 parent 17a580b commit 5a83396
Show file tree
Hide file tree
Showing 17 changed files with 1,682 additions and 1,229 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ npm-debug.log
.npmrc
# output
dist
.DS_Store
*.log
55 changes: 40 additions & 15 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ interface PkgTree {
hasDevDependencies?: boolean;
}

interface TargetFile {
name?: string;
dependencies?: {
[dep: string]: object;
};
devDependencies?: {
[dep: string]: object;
};
}

export {
buildDepTree,
buildDepTreeFromFiles,
Expand All @@ -30,12 +40,9 @@ async function buildDepTree(targetFileRaw: string, lockFileRaw: string, includeD
const lockFile = JSON.parse(lockFileRaw);
const targetFile = JSON.parse(targetFileRaw);

if (!targetFile.dependencies) {
if (!targetFile.dependencies && !includeDev) {
throw new Error("No 'dependencies' property in package.json");
}
if (!lockFile.dependencies) {
throw new Error("No 'dependencies' property in package-lock.json");
}

const depTree: PkgTree = {
dependencies: {},
Expand All @@ -44,23 +51,38 @@ async function buildDepTree(targetFileRaw: string, lockFileRaw: string, includeD
version: targetFile.version,
};

const topLevelDeps = Object.keys(targetFile.dependencies);
// asked to process empty deps
if (_.isEmpty(targetFile.dependencies) && !includeDev) {
return depTree;
}

if (!lockFile.dependencies && !includeDev) {
throw new Error("No 'dependencies' property in package-lock.json");
}
const topLevelDeps = getTopLevelDeps(targetFile, includeDev);

await Promise.all(topLevelDeps.map(async (dep) => {
depTree.dependencies[dep] = await buildSubTreeRecursive(dep, [], lockFile);
}));

return depTree;
}

function getTopLevelDeps(targetFile: TargetFile, includeDev: boolean): string[] {
let topLevelDeps = targetFile.dependencies;

if (includeDev && targetFile.devDependencies) {
const topLevelDevDeps = Object.keys(targetFile.devDependencies);
await Promise.all(topLevelDevDeps.map(async (dep) => {
depTree.dependencies[dep] = await buildSubTreeRecursive(dep, [], lockFile);
}));
topLevelDeps = {
...topLevelDeps,
...targetFile.devDependencies,
};
}

return depTree;
return _.uniq(Object.keys(topLevelDeps));
}

async function buildSubTreeRecursive(dep: string, depKeys: string[], lockFile: object): Promise<PkgTree> {
async function buildSubTreeRecursive(
dep: string, depKeys: string[], lockFile: object): Promise<PkgTree> {

const depSubTree: PkgTree = {
depType: undefined,
Expand All @@ -82,9 +104,12 @@ async function buildSubTreeRecursive(dep: string, depKeys: string[], lockFile: o
depSubTree.depType = deps[dep].dev ? DepType.dev : DepType.prod;
// repeat the process for dependencies of looked-up dep
const newDeps = deps[dep].requires ? Object.keys(deps[dep].requires) : [];

await Promise.all(newDeps.map(async (subDep) => {
depSubTree.dependencies[subDep] = await buildSubTreeRecursive(subDep, [...depKeys, dep], lockFile);
}));
depSubTree.dependencies[subDep] = await buildSubTreeRecursive(subDep,
[...depKeys, dep], lockFile);
}),
);
return depSubTree;
} else {
// tree was walked to the root and dependency was not found
Expand All @@ -109,7 +134,7 @@ function getDepPath(depKeys: string[]) {
async function buildDepTreeFromFiles(
root: string, targetFilePath: string, lockFilePath: string, includeDev = false): Promise<PkgTree> {
if (!root || !lockFilePath || !lockFilePath) {
throw new Error('Missing required parameters for parseLockFile()');
throw new Error('Missing required parameters for buildDepTreeFromFiles()');
}

const targetFileFullPath = path.resolve(root, targetFilePath);
Expand All @@ -119,7 +144,7 @@ async function buildDepTreeFromFiles(
throw new Error(`Target file package.json not found at location: ${targetFileFullPath}`);
}
if (!fs.existsSync(lockFileFullPath)) {
throw new Error(`LockFile package-lock.json not found at location: ${lockFileFullPath}`);
throw new Error(`Lockfile package-lock.json not found at location: ${lockFileFullPath}`);
}

const targetFile = fs.readFileSync(targetFileFullPath, 'utf-8');
Expand Down
Loading

0 comments on commit 5a83396

Please sign in to comment.