Skip to content

Commit

Permalink
feat: support using custom registry #70
Browse files Browse the repository at this point in the history
  • Loading branch information
regevbr committed May 9, 2020
1 parent 56bedde commit 0eb63d3
Show file tree
Hide file tree
Showing 16 changed files with 356 additions and 103 deletions.
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"lcov",
"toolbelt",
"Conosla",
"libnpmconfig",
"packument"
],
"ignorePaths": [
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,6 @@ typings/
# stryker temp files
.stryker-tmp
/reports
!@types/**
!/tools

3 changes: 3 additions & 0 deletions @types/libnpmconfig/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module 'libnpmconfig' {
export function read(): Record<string, any>;
}
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"@types/jest-when": "^2.7.1",
"@types/node": "^13.13.5",
"@types/node-fetch": "^2.5.7",
"@types/npm-registry-fetch": "^8.0.0",
"@types/pacote": "^11.1.0",
"@types/semver": "^7.1.0",
"@types/shell-quote": "^1.6.1",
Expand All @@ -98,9 +99,9 @@
"@typescript-eslint/parser": "^2.31.0",
"all-contributors-cli": "^6.14.2",
"cspell": "^4.0.61",
"eslint": "^6.8.0",
"eslint": "^7.0.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-jest": "^23.9.0",
"eslint-plugin-jest": "^23.10.0",
"eslint-plugin-prefer-arrow": "^1.2.1",
"eslint-plugin-prettier": "^3.1.3",
"expect": "^26.0.1",
Expand All @@ -113,12 +114,12 @@
"lint-staged": "^10.2.2",
"mock-spawn": "^0.2.6",
"node-fetch": "^2.6.0",
"npm-check-updates": "^4.1.2",
"npm-check-updates": "^5.0.0",
"prettier": "^2.0.5",
"semver": "^7.3.2",
"ts-jest": "^25.5.0",
"ts-jest": "^25.5.1",
"ts-node": "^8.10.1",
"ts-toolbelt": "^6.6.2",
"ts-toolbelt": "^6.7.2",
"typescript": "^3.8.3"
},
"dependencies": {
Expand All @@ -129,6 +130,7 @@
"cross-spawn": "~7.0.2",
"figures": "~3.2.0",
"inversify": "~5.0.1",
"libnpmconfig": "^1.2.1",
"moment": "~2.25.3",
"pacote": "~11.1.9",
"reflect-metadata": "~0.1.13",
Expand Down
4 changes: 4 additions & 0 deletions src/container/nodeModulesContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import * as fs from 'fs';
import * as pacote from 'pacote';
import * as simpleGit from 'simple-git/promise';
import * as spawn from 'cross-spawn';
import * as libnpmconfig from 'libnpmconfig';
import axios from 'axios';
import { interfaces } from 'inversify';
import Bind = interfaces.Bind;

export type LibNpmConfig = typeof libnpmconfig;
export type Spawn = typeof spawn;
export type Axios = typeof axios;
export type Pacote = typeof pacote;
Expand All @@ -20,6 +22,7 @@ export const TYPES = {
Spawn: Symbol.for(`Spawn`),
SimpleGit: Symbol.for(`SimpleGit`),
Axios: Symbol.for(`Axios`),
LibNpmConfig: Symbol.for(`LibNpmConfig`),
};

export const nodeModulesBinder = (bind: Bind): void => {
Expand All @@ -29,4 +32,5 @@ export const nodeModulesBinder = (bind: Bind): void => {
bind<Spawn>(TYPES.Spawn).toConstantValue(spawn);
bind<SimpleGitFn>(TYPES.SimpleGit).toConstantValue(simpleGit);
bind<Axios>(TYPES.Axios).toConstantValue(axios);
bind<LibNpmConfig>(TYPES.LibNpmConfig).toConstantValue(libnpmconfig);
};
50 changes: 50 additions & 0 deletions src/utils/packageInfo/impl/configRetriever.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { inject, injectable } from 'inversify';
import { ILogger } from '../../logger/interfaces/ILogger';
import { LibNpmConfig, TYPES } from '../../../container/nodeModulesContainer';
import { ILoggerFactory } from '../../logger';
import { INpmConfig, INpmConfigRetriever } from '../interfaces/INpmConfigRetriever';
import { isBoolean, isString } from 'ts-type-guards';

const coerceBoolean = (value: undefined | string | boolean): boolean => {
if (value === undefined || value === null) {
return false;
}
if (isBoolean(value)) {
return value;
}
return value.toLowerCase() === `true`;
};

@injectable()
export class NpmConfigRetriever extends INpmConfigRetriever {
private readonly logger: ILogger;

constructor(@inject(TYPES.LibNpmConfig) private readonly libnpmconfig: LibNpmConfig, loggerFactory: ILoggerFactory) {
super();
this.logger = loggerFactory.getLogger(`Npm Config Retriever`);
}

async retrieve(): Promise<INpmConfig> {
this.logger.info(`Reading npm config`);
const result = this.libnpmconfig.read();
const npmConfig: INpmConfig = {};
result.forEach((value: any, key: string) => {
if (isString(value) && key.indexOf(`:`) > 0) {
npmConfig[key] = value;
}
});
npmConfig[`always-auth`] = coerceBoolean(result[`always-auth`]);
npmConfig.strictSSL = coerceBoolean(result[`strict-ssl`]);
npmConfig.alwaysAuth = coerceBoolean(result.alwaysAuth);
npmConfig.registry = result.registry;
npmConfig.username = result.username;
npmConfig.password = result.password;
npmConfig.token = result.token;
// eslint-disable-next-line no-underscore-dangle
npmConfig._authToken = result._authToken;
// eslint-disable-next-line no-underscore-dangle
npmConfig._auth = result._auth;
npmConfig.email = result.email;
return npmConfig;
}
}
50 changes: 50 additions & 0 deletions src/utils/packageInfo/impl/npmConfigRetriever.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { inject, injectable } from 'inversify';
import { ILogger } from '../../logger/interfaces/ILogger';
import { LibNpmConfig, TYPES } from '../../../container/nodeModulesContainer';
import { ILoggerFactory } from '../../logger';
import { INpmConfig, INpmConfigRetriever } from '../interfaces/INpmConfigRetriever';
import { isBoolean, isString } from 'ts-type-guards';

const coerceBoolean = (value: undefined | string | boolean): boolean => {
if (value === undefined || value === null) {
return false;
}
if (isBoolean(value)) {
return value;
}
return value.toLowerCase() === `true`;
};

@injectable()
export class NpmConfigRetriever extends INpmConfigRetriever {
private readonly logger: ILogger;

constructor(@inject(TYPES.LibNpmConfig) private readonly libnpmconfig: LibNpmConfig, loggerFactory: ILoggerFactory) {
super();
this.logger = loggerFactory.getLogger(`Npm Config Retriever`);
}

async retrieve(): Promise<INpmConfig> {
this.logger.info(`Reading npm config`);
const result = this.libnpmconfig.read();
const npmConfig: INpmConfig = {};
result.forEach((value: any, key: string) => {
if (isString(value) && key.indexOf(`:`) > 0) {
npmConfig[key] = value;
}
});
npmConfig[`always-auth`] = coerceBoolean(result[`always-auth`]);
npmConfig.strictSSL = coerceBoolean(result[`strict-ssl`]);
npmConfig.alwaysAuth = coerceBoolean(result.alwaysAuth);
npmConfig.registry = result.registry;
npmConfig.username = result.username;
npmConfig.password = result.password;
npmConfig.token = result.token;
// eslint-disable-next-line no-underscore-dangle
npmConfig._authToken = result._authToken;
// eslint-disable-next-line no-underscore-dangle
npmConfig._auth = result._auth;
npmConfig.email = result.email;
return npmConfig;
}
}
4 changes: 4 additions & 0 deletions src/utils/packageInfo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ import { IPackageInfo } from './interfaces/IPackageInfo';
import { PackageInfo } from './impl/packageInfo';
import { interfaces } from 'inversify';
import Bind = interfaces.Bind;
import { NpmConfigRetriever } from './impl/npmConfigRetriever';
import { INpmConfigRetriever } from './interfaces/INpmConfigRetriever';

export const packageInfoModulesBinder = (bind: Bind): void => {
bind<INpmConfigRetriever>(INpmConfigRetriever).to(NpmConfigRetriever).inSingletonScope();
bind<IPackageInfo>(IPackageInfo).to(PackageInfo).inSingletonScope();
};

export * from './interfaces/IPackageInfo';
export * from './interfaces/INpmConfigRetriever';
7 changes: 7 additions & 0 deletions src/utils/packageInfo/interfaces/INpmConfigRetriever.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Options } from 'npm-registry-fetch';

export type INpmConfig = Options;

export abstract class INpmConfigRetriever {
public abstract async retrieve(): Promise<INpmConfig>;
}
6 changes: 6 additions & 0 deletions test/src/container/nodeModulesContainer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as spawn from 'cross-spawn';
import axios from 'axios';
import { BindingTypes, testBindings } from '../../common/testers/bindingTester';
import { nodeModulesBinder, TYPES } from '../../../src/container/nodeModulesContainer';
import * as libnpmconfig from 'libnpmconfig';

testBindings({
name: `node module container`,
Expand Down Expand Up @@ -41,5 +42,10 @@ testBindings({
binded: axios,
type: BindingTypes.CONSTANT,
},
{
binder: TYPES.LibNpmConfig,
binded: libnpmconfig,
type: BindingTypes.CONSTANT,
},
],
});
12 changes: 12 additions & 0 deletions test/src/utils/packageInfo/impl/npmConfigRetriever.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as libnpmconfig from 'libnpmconfig';
import { loggerFactory } from '../../../../common/logger';
import { NpmConfigRetriever } from '../../../../../src/utils/packageInfo/impl/npmConfigRetriever';

describe(`npm config retriever`, () => {
const npmConfigRetriever = new NpmConfigRetriever(libnpmconfig, loggerFactory);

it(`should return npm config`, async () => {
const result = await npmConfigRetriever.retrieve();
expect(result).toEqual({});
});
});
8 changes: 7 additions & 1 deletion test/src/utils/packageInfo/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { BindingTypes, testBindings } from '../../../common/testers/bindingTester';
import { IPackageInfo, packageInfoModulesBinder } from '../../../../src/utils/packageInfo';
import { INpmConfigRetriever, IPackageInfo, packageInfoModulesBinder } from '../../../../src/utils/packageInfo';
import { PackageInfo } from '../../../../src/utils/packageInfo/impl/packageInfo';
import { NpmConfigRetriever } from '../../../../src/utils/packageInfo/impl/npmConfigRetriever';

testBindings({
name: `package info module container`,
binderFn: packageInfoModulesBinder,
bindings: [
{
binder: INpmConfigRetriever,
binded: NpmConfigRetriever,
type: BindingTypes.SINGELTON,
},
{
binder: IPackageInfo,
binded: PackageInfo,
Expand Down
4 changes: 2 additions & 2 deletions testE2E/src/utils/packageInfo/impl/packageInfo.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ describe(`package info e2e`, () => {

it(`should resolve package version properly`, async () => {
const result = await packageInfo.resolvePackageVersion({
name: `squiss-ts`,
semver: `~3.0.0`,
name: `@pruvo/common`,
semver: `~1.0.0`,
});
expect(result).toEqual(`3.0.1`);
}, 30000);
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.build.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"declaration": true,
"outDir": "dist"
},
"include": ["src"]
"include": ["src", "@types/**/*.d.ts"]
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": ["src", "test", "testE2E", "testInteg", "tools"]
"include": ["src", "test", "testE2E", "testInteg", "tools", "@types/**/*.d.ts"]
}
Loading

0 comments on commit 0eb63d3

Please sign in to comment.