Skip to content

Commit

Permalink
feat: add package.json parser #20
Browse files Browse the repository at this point in the history
  • Loading branch information
regevbr committed Apr 22, 2020
1 parent 04f2b42 commit 6fd6508
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 7 deletions.
2 changes: 2 additions & 0 deletions src/container/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { packageInfoModulesBinder } from '../utils/packageInfo';
import { nodeModulesBinder } from './nodeModulesContainer';
import { enginesResolveModulesBinder } from '../resolvers/enginesResolver';
import { loggerModuleBinder } from '../utils/logger';
import { packageJsonParserModulesBinder } from '../utils/packageJsonParser';

export const container = new Container({
skipBaseClassChecks: true,
Expand All @@ -34,6 +35,7 @@ const binders: Binder[] = [
packageInfoModulesBinder,
enginesResolveModulesBinder,
loggerModuleBinder,
packageJsonParserModulesBinder,
];

container.load(
Expand Down
7 changes: 1 addition & 6 deletions src/dependencyChecker/interfaces/IDependencyChecker.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { Moment } from 'moment';

export enum DependencyType {
PROD = `production`,
DEV = `development`,
PEER = `peer`,
}
import { DependencyType } from '../../utils/packageJsonParser';

export interface IDependencyCheckerRunOptions {
pkg: {
Expand Down
66 changes: 66 additions & 0 deletions src/utils/packageJsonParser/impl/packageJsonParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { inject, injectable } from 'inversify';
import { FS, TYPES } from '../../../container/nodeModulesContainer';
import { ILoggerFactory } from '../../logger';
import { ILogger } from '../../logger/interfaces/ILogger';
import { Dependency, DependencyType, IPackageJsonData, IPackageJsonParseOptions, IPackageJsonParser } from '..';
import * as path from 'path';
import { Manifest } from 'pacote';

const PKG_FILE = `package.json`;

@injectable()
export class PackageJsonParser extends IPackageJsonParser {
private readonly logger: ILogger;

constructor(@inject(TYPES.FS) private readonly fs: FS, loggerFactory: ILoggerFactory) {
super();
this.logger = loggerFactory.getLogger(`Package Json Parser`);
}

public async parse({ cwd, include }: IPackageJsonParseOptions): Promise<IPackageJsonData> {
this.logger.info(`Reading package.json information`);
const pgkFilePath = path.join(cwd, PKG_FILE);
this.logger.debug(`Reading file`, pgkFilePath);
const content = await this.fs.promises.readFile(pgkFilePath, `utf-8`);
const pkg: Manifest = JSON.parse(content);
const dependencies = new Set<Dependency>();
// handle filtering
this.handleDepType(include.dev, pkg.devDependencies, DependencyType.DEV, dependencies, `dev`);
this.handleDepType(include.prod, pkg.dependencies, DependencyType.PROD, dependencies, `production`);
this.handleDepType(include.peer, pkg.peerDependencies, DependencyType.PEER, dependencies, `peer`);
this.handleDepType(include.optional, pkg.optionalDependencies, DependencyType.OPTIONAL, dependencies, `optional`);
const scripts = pkg.scripts || {};
this.logger.info(`Going to check ${dependencies.size} dependencies`);
return {
scripts,
dependencies,
};
}

private handleDepType(
included: boolean,
list: undefined | Record<string, string>,
type: DependencyType,
deps: Set<Dependency>,
typeStr: string,
): void {
if (included) {
if (list) {
let count = 0;
for (const [name, semver] of Object.entries(list)) {
count++;
deps.add({
name,
semver,
dependencyType: type,
});
}
this.logger.info(`Found ${count} ${typeStr} dependencies`);
} else {
this.logger.info(`No ${typeStr} dependencies defined`);
}
} else {
this.logger.info(`Skipping ${typeStr} dependencies`);
}
}
}
10 changes: 10 additions & 0 deletions src/utils/packageJsonParser/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { interfaces } from 'inversify';
import Bind = interfaces.Bind;
import { IPackageJsonParser } from './interfaces/IPackageJsonParser';
import { PackageJsonParser } from './impl/packageJsonParser';

export const packageJsonParserModulesBinder = (bind: Bind): void => {
bind<IPackageJsonParser>(IPackageJsonParser).to(PackageJsonParser).inSingletonScope();
};

export * from './interfaces/IPackageJsonParser';
36 changes: 36 additions & 0 deletions src/utils/packageJsonParser/interfaces/IPackageJsonParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export enum DependencyType {
PROD = `production`,
DEV = `development`,
PEER = `peer`,
OPTIONAL = `optional`,
GLOBAL = `global`,
}

export type Scripts = Record<string, string>;

export interface Dependency {
semver: string;
name: string;
dependencyType: DependencyType;
}

export interface IPackageJsonParseOptions {
cwd: string;
packageFile: string | undefined;
include: {
prod: boolean;
dev: boolean;
optional: boolean;
peer: boolean;
global: boolean;
};
}

export interface IPackageJsonData {
dependencies: Set<Dependency>;
scripts: Scripts;
}

export abstract class IPackageJsonParser {
public abstract async parse(options: IPackageJsonParseOptions): Promise<IPackageJsonData>;
}
2 changes: 1 addition & 1 deletion test/src/utils/nodeVersions/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { INodeVersions, nodeVersionsModulesBinder } from '../../../../src/utils/
import { NodeVersions } from '../../../../src/utils/nodeVersions/impl/nodeVersions';

testBindings({
name: `lts module container`,
name: `node version module container`,
binderFn: nodeVersionsModulesBinder,
bindings: [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
describe(`package json parser`, () => {
it(`dummy`, () => {
expect(1).toBe(1);
});
});
15 changes: 15 additions & 0 deletions test/src/utils/packageJsonParser/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { BindingTypes, testBindings } from '../../../common/testers/bindingTester';
import { IPackageJsonParser, packageJsonParserModulesBinder } from '../../../../src/utils/packageJsonParser';
import { PackageJsonParser } from '../../../../src/utils/packageJsonParser/impl/packageJsonParser';

testBindings({
name: `package json parser module container`,
binderFn: packageJsonParserModulesBinder,
bindings: [
{
binder: IPackageJsonParser,
binded: PackageJsonParser,
type: BindingTypes.SINGELTON,
},
],
});

0 comments on commit 6fd6508

Please sign in to comment.