test: Increase coverage for unit test (#974)
* test(utils): add test for validate names * test(utils): add unit test for dist-tags normalize utility * refactor(notifications): unit test for notifications * test(cli): add unit test for address validation * chore: add new constants * chore: ignore debug from coverage * test(bootstrap): test https is fails on start * refactor: update code for rebase
This commit is contained in:
parent
7e78209474
commit
cf31982127
|
@ -1,5 +1,5 @@
|
|||
// flow-typed signature: 4cacceffd326bb118e4a3c1b4d629e98
|
||||
// flow-typed version: e737b9832f/jest_v23.x.x/flow_>=v0.39.x
|
||||
// flow-typed signature: f5a484315a3dea13d273645306e4076a
|
||||
// flow-typed version: 7c5d14b3d4/jest_v23.x.x/flow_>=v0.39.x
|
||||
|
||||
type JestMockFn<TArguments: $ReadOnlyArray<*>, TReturn> = {
|
||||
(...args: TArguments): TReturn,
|
||||
|
@ -65,7 +65,7 @@ type JestMockFn<TArguments: $ReadOnlyArray<*>, TReturn> = {
|
|||
*/
|
||||
mockReturnThis(): void,
|
||||
/**
|
||||
* Deprecated: use jest.fn(() => value) instead
|
||||
* Accepts a value that will be returned whenever the mock function is called.
|
||||
*/
|
||||
mockReturnValue(value: TReturn): JestMockFn<TArguments, TReturn>,
|
||||
/**
|
||||
|
@ -140,6 +140,30 @@ type JestPromiseType = {
|
|||
*/
|
||||
type JestTestName = string | Function;
|
||||
|
||||
/**
|
||||
* Plugin: jest-styled-components
|
||||
*/
|
||||
|
||||
type JestStyledComponentsMatcherValue =
|
||||
| string
|
||||
| JestAsymmetricEqualityType
|
||||
| RegExp
|
||||
| typeof undefined;
|
||||
|
||||
type JestStyledComponentsMatcherOptions = {
|
||||
media?: string;
|
||||
modifier?: string;
|
||||
supports?: string;
|
||||
}
|
||||
|
||||
type JestStyledComponentsMatchersType = {
|
||||
toHaveStyleRule(
|
||||
property: string,
|
||||
value: JestStyledComponentsMatcherValue,
|
||||
options?: JestStyledComponentsMatcherOptions
|
||||
): void,
|
||||
};
|
||||
|
||||
/**
|
||||
* Plugin: jest-enzyme
|
||||
*/
|
||||
|
@ -500,7 +524,13 @@ type JestExtendedMatchersType = {
|
|||
};
|
||||
|
||||
interface JestExpectType {
|
||||
not: JestExpectType & EnzymeMatchersType & DomTestingLibraryType & JestJQueryMatchersType & JestExtendedMatchersType,
|
||||
not:
|
||||
& JestExpectType
|
||||
& EnzymeMatchersType
|
||||
& DomTestingLibraryType
|
||||
& JestJQueryMatchersType
|
||||
& JestStyledComponentsMatchersType
|
||||
& JestExtendedMatchersType,
|
||||
/**
|
||||
* If you have a mock function, you can use .lastCalledWith to test what
|
||||
* arguments it was last called with.
|
||||
|
@ -664,6 +694,9 @@ interface JestExpectType {
|
|||
* This ensures that an Object matches the most recent snapshot.
|
||||
*/
|
||||
toMatchSnapshot(name: string): void,
|
||||
|
||||
toMatchInlineSnapshot(snapshot?: string): void,
|
||||
toMatchInlineSnapshot(propertyMatchers?: {[key: string]: JestAsymmetricEqualityType}, snapshot?: string): void,
|
||||
/**
|
||||
* Use .toThrow to test that a function throws when it is called.
|
||||
* If you want to test that a specific error gets thrown, you can provide an
|
||||
|
@ -678,7 +711,8 @@ interface JestExpectType {
|
|||
* Use .toThrowErrorMatchingSnapshot to test that a function throws a error
|
||||
* matching the most recent snapshot when it is called.
|
||||
*/
|
||||
toThrowErrorMatchingSnapshot(): void
|
||||
toThrowErrorMatchingSnapshot(): void,
|
||||
toThrowErrorMatchingInlineSnapshot(snapshot?: string): void,
|
||||
}
|
||||
|
||||
type JestObjectType = {
|
||||
|
@ -897,6 +931,17 @@ declare var it: {
|
|||
fn?: (done: () => void) => ?Promise<mixed>,
|
||||
timeout?: number
|
||||
): void,
|
||||
/**
|
||||
* each runs this test against array of argument arrays per each run
|
||||
*
|
||||
* @param {table} table of Test
|
||||
*/
|
||||
each(
|
||||
table: Array<Array<mixed>>
|
||||
): (
|
||||
name: JestTestName,
|
||||
fn?: (...args: Array<any>) => ?Promise<mixed>
|
||||
) => void,
|
||||
/**
|
||||
* Only run this test
|
||||
*
|
||||
|
@ -908,7 +953,14 @@ declare var it: {
|
|||
name: JestTestName,
|
||||
fn?: (done: () => void) => ?Promise<mixed>,
|
||||
timeout?: number
|
||||
): void,
|
||||
): {
|
||||
each(
|
||||
table: Array<Array<mixed>>
|
||||
): (
|
||||
name: JestTestName,
|
||||
fn?: (...args: Array<any>) => ?Promise<mixed>
|
||||
) => void,
|
||||
},
|
||||
/**
|
||||
* Skip running this test
|
||||
*
|
||||
|
@ -999,7 +1051,15 @@ type JestPrettyFormatPlugins = Array<JestPrettyFormatPlugin>;
|
|||
/** The expect function is used every time you want to test a value */
|
||||
declare var expect: {
|
||||
/** The object that you want to make assertions against */
|
||||
(value: any): JestExpectType & JestPromiseType & EnzymeMatchersType & DomTestingLibraryType & JestJQueryMatchersType & JestExtendedMatchersType,
|
||||
(value: any):
|
||||
& JestExpectType
|
||||
& JestPromiseType
|
||||
& EnzymeMatchersType
|
||||
& DomTestingLibraryType
|
||||
& JestJQueryMatchersType
|
||||
& JestStyledComponentsMatchersType
|
||||
& JestExtendedMatchersType,
|
||||
|
||||
/** Add additional Jasmine matchers to Jest's roster */
|
||||
extend(matchers: { [name: string]: JestMatcher }): void,
|
||||
/** Add a module that formats application-specific data structures. */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// flow-typed signature: a0ace6ecf9cb0e9f971f651691137591
|
||||
// flow-typed version: e4e1d58043/lodash_v4.x.x/flow_>=v0.63.x
|
||||
// flow-typed signature: 1b1fe531123a979fe1c4624ccc62bd5a
|
||||
// flow-typed version: dea0770be9/lodash_v4.x.x/flow_>=v0.63.x
|
||||
|
||||
declare module "lodash" {
|
||||
declare type __CurriedFunction1<A, R, AA: A> = (...r: [AA]) => R;
|
||||
|
@ -193,7 +193,7 @@ declare module "lodash" {
|
|||
) => mixed;
|
||||
declare type Iteratee<T> = _Iteratee<T> | Object | string;
|
||||
declare type FlatMapIteratee<T, U> =
|
||||
| ((item: T, index: number, array: ?Array<T>) => Array<U>)
|
||||
| ((item: T, index: number, array: ?$ReadOnlyArray<T>) => Array<U>)
|
||||
| Object
|
||||
| string;
|
||||
declare type Comparator<T> = (item: T, item2: T) => boolean;
|
||||
|
@ -214,8 +214,8 @@ declare module "lodash" {
|
|||
// Array
|
||||
chunk<T>(array?: ?Array<T>, size?: ?number): Array<Array<T>>;
|
||||
compact<T, N: ?T>(array?: ?Array<N>): Array<T>;
|
||||
concat<T>(base?: ?Array<T>, ...elements: Array<any>): Array<T | any>;
|
||||
difference<T>(array?: ?$ReadOnlyArray<T>, values?: ?$ReadOnlyArray<T>): Array<T>;
|
||||
concat<T>(base?: ?$ReadOnlyArray<T>, ...elements: Array<any>): Array<T | any>;
|
||||
difference<T>(array?: ?$ReadOnlyArray<T>, ...values: Array<?$ReadOnlyArray<T>>): Array<T>;
|
||||
differenceBy<T>(
|
||||
array?: ?$ReadOnlyArray<T>,
|
||||
values?: ?$ReadOnlyArray<T>,
|
||||
|
@ -253,59 +253,59 @@ declare module "lodash" {
|
|||
fromIndex?: ?number
|
||||
): -1;
|
||||
// alias of _.head
|
||||
first<T>(array: ?Array<T>): T;
|
||||
first<T>(array: ?$ReadOnlyArray<T>): T;
|
||||
flatten<T, X>(array?: ?Array<Array<T> | X>): Array<T | X>;
|
||||
flattenDeep<T>(array?: ?any[]): Array<T>;
|
||||
flattenDepth(array?: ?any[], depth?: ?number): any[];
|
||||
fromPairs<A, B>(pairs?: ?Array<[A, B]>): { [key: A]: B };
|
||||
head<T>(array: ?Array<T>): T;
|
||||
head<T>(array: ?$ReadOnlyArray<T>): T;
|
||||
indexOf<T>(array: Array<T>, value: T, fromIndex?: number): number;
|
||||
indexOf<T>(array: void | null, value?: ?T, fromIndex?: ?number): -1;
|
||||
initial<T>(array: ?Array<T>): Array<T>;
|
||||
intersection<T>(...arrays?: Array<Array<T>>): Array<T>;
|
||||
intersection<T>(...arrays?: Array<$ReadOnlyArray<T>>): Array<T>;
|
||||
//Workaround until (...parameter: T, parameter2: U) works
|
||||
intersectionBy<T>(a1?: ?Array<T>, iteratee?: ?ValueOnlyIteratee<T>): Array<T>;
|
||||
intersectionBy<T>(a1?: ?$ReadOnlyArray<T>, iteratee?: ?ValueOnlyIteratee<T>): Array<T>;
|
||||
intersectionBy<T>(
|
||||
a1?: ?Array<T>,
|
||||
a2?: ?Array<T>,
|
||||
a1?: ?$ReadOnlyArray<T>,
|
||||
a2?: ?$ReadOnlyArray<T>,
|
||||
iteratee?: ?ValueOnlyIteratee<T>
|
||||
): Array<T>;
|
||||
intersectionBy<T>(
|
||||
a1?: ?Array<T>,
|
||||
a2?: ?Array<T>,
|
||||
a3?: ?Array<T>,
|
||||
a1?: ?$ReadOnlyArray<T>,
|
||||
a2?: ?$ReadOnlyArray<T>,
|
||||
a3?: ?$ReadOnlyArray<T>,
|
||||
iteratee?: ?ValueOnlyIteratee<T>
|
||||
): Array<T>;
|
||||
intersectionBy<T>(
|
||||
a1?: ?Array<T>,
|
||||
a2?: ?Array<T>,
|
||||
a3?: ?Array<T>,
|
||||
a4?: ?Array<T>,
|
||||
a1?: ?$ReadOnlyArray<T>,
|
||||
a2?: ?$ReadOnlyArray<T>,
|
||||
a3?: ?$ReadOnlyArray<T>,
|
||||
a4?: ?$ReadOnlyArray<T>,
|
||||
iteratee?: ?ValueOnlyIteratee<T>
|
||||
): Array<T>;
|
||||
//Workaround until (...parameter: T, parameter2: U) works
|
||||
intersectionWith<T>(a1?: ?Array<T>, comparator?: ?Comparator<T>): Array<T>;
|
||||
intersectionWith<T>(a1?: ?$ReadOnlyArray<T>, comparator?: ?Comparator<T>): Array<T>;
|
||||
intersectionWith<T>(
|
||||
a1?: ?Array<T>,
|
||||
a2?: ?Array<T>,
|
||||
a1?: ?$ReadOnlyArray<T>,
|
||||
a2?: ?$ReadOnlyArray<T>,
|
||||
comparator?: ?Comparator<T>
|
||||
): Array<T>;
|
||||
intersectionWith<T>(
|
||||
a1?: ?Array<T>,
|
||||
a2?: ?Array<T>,
|
||||
a3?: ?Array<T>,
|
||||
a1?: ?$ReadOnlyArray<T>,
|
||||
a2?: ?$ReadOnlyArray<T>,
|
||||
a3?: ?$ReadOnlyArray<T>,
|
||||
comparator?: ?Comparator<T>
|
||||
): Array<T>;
|
||||
intersectionWith<T>(
|
||||
a1?: ?Array<T>,
|
||||
a2?: ?Array<T>,
|
||||
a3?: ?Array<T>,
|
||||
a4?: ?Array<T>,
|
||||
a1?: ?$ReadOnlyArray<T>,
|
||||
a2?: ?$ReadOnlyArray<T>,
|
||||
a3?: ?$ReadOnlyArray<T>,
|
||||
a4?: ?$ReadOnlyArray<T>,
|
||||
comparator?: ?Comparator<T>
|
||||
): Array<T>;
|
||||
join<T>(array: Array<T>, separator?: ?string): string;
|
||||
join<T>(array: void | null, separator?: ?string): '';
|
||||
last<T>(array: ?Array<T>): T;
|
||||
last<T>(array: ?$ReadOnlyArray<T>): T;
|
||||
lastIndexOf<T>(array: Array<T>, value?: ?T, fromIndex?: ?number): number;
|
||||
lastIndexOf<T>(array: void | null, value?: ?T, fromIndex?: ?number): -1;
|
||||
nth<T>(array: T[], n?: ?number): T;
|
||||
|
@ -331,7 +331,7 @@ declare module "lodash" {
|
|||
remove<T>(array?: ?Array<T>, predicate?: ?Predicate<T>): Array<T>;
|
||||
reverse<T>(array: Array<T>): Array<T>;
|
||||
reverse<T: void | null>(array: T): T;
|
||||
slice<T>(array?: ?Array<T>, start?: ?number, end?: ?number): Array<T>;
|
||||
slice<T>(array?: ?$ReadOnlyArray<T>, start?: ?number, end?: ?number): Array<T>;
|
||||
sortedIndex<T>(array: Array<T>, value: T): number;
|
||||
sortedIndex<T>(array: void | null, value: ?T): 0;
|
||||
sortedIndexBy<T>(
|
||||
|
@ -367,45 +367,45 @@ declare module "lodash" {
|
|||
takeRight<T>(array?: ?Array<T>, n?: ?number): Array<T>;
|
||||
takeRightWhile<T>(array?: ?Array<T>, predicate?: ?Predicate<T>): Array<T>;
|
||||
takeWhile<T>(array?: ?Array<T>, predicate?: ?Predicate<T>): Array<T>;
|
||||
union<T>(...arrays?: Array<Array<T>>): Array<T>;
|
||||
union<T>(...arrays?: Array<$ReadOnlyArray<T>>): Array<T>;
|
||||
//Workaround until (...parameter: T, parameter2: U) works
|
||||
unionBy<T>(a1?: ?Array<T>, iteratee?: ?ValueOnlyIteratee<T>): Array<T>;
|
||||
unionBy<T>(a1?: ?$ReadOnlyArray<T>, iteratee?: ?ValueOnlyIteratee<T>): Array<T>;
|
||||
unionBy<T>(
|
||||
a1?: ?Array<T>,
|
||||
a2: Array<T>,
|
||||
a1?: ?$ReadOnlyArray<T>,
|
||||
a2: $ReadOnlyArray<T>,
|
||||
iteratee?: ValueOnlyIteratee<T>
|
||||
): Array<T>;
|
||||
unionBy<T>(
|
||||
a1: Array<T>,
|
||||
a2: Array<T>,
|
||||
a3: Array<T>,
|
||||
a1: $ReadOnlyArray<T>,
|
||||
a2: $ReadOnlyArray<T>,
|
||||
a3: $ReadOnlyArray<T>,
|
||||
iteratee?: ValueOnlyIteratee<T>
|
||||
): Array<T>;
|
||||
unionBy<T>(
|
||||
a1: Array<T>,
|
||||
a2: Array<T>,
|
||||
a3: Array<T>,
|
||||
a4: Array<T>,
|
||||
a1: $ReadOnlyArray<T>,
|
||||
a2: $ReadOnlyArray<T>,
|
||||
a3: $ReadOnlyArray<T>,
|
||||
a4: $ReadOnlyArray<T>,
|
||||
iteratee?: ValueOnlyIteratee<T>
|
||||
): Array<T>;
|
||||
//Workaround until (...parameter: T, parameter2: U) works
|
||||
unionWith<T>(a1?: ?Array<T>, comparator?: ?Comparator<T>): Array<T>;
|
||||
unionWith<T>(
|
||||
a1: Array<T>,
|
||||
a2: Array<T>,
|
||||
a1: $ReadOnlyArray<T>,
|
||||
a2: $ReadOnlyArray<T>,
|
||||
comparator?: Comparator<T>
|
||||
): Array<T>;
|
||||
unionWith<T>(
|
||||
a1: Array<T>,
|
||||
a2: Array<T>,
|
||||
a3: Array<T>,
|
||||
a1: $ReadOnlyArray<T>,
|
||||
a2: $ReadOnlyArray<T>,
|
||||
a3: $ReadOnlyArray<T>,
|
||||
comparator?: Comparator<T>
|
||||
): Array<T>;
|
||||
unionWith<T>(
|
||||
a1: Array<T>,
|
||||
a2: Array<T>,
|
||||
a3: Array<T>,
|
||||
a4: Array<T>,
|
||||
a1: $ReadOnlyArray<T>,
|
||||
a2: $ReadOnlyArray<T>,
|
||||
a3: $ReadOnlyArray<T>,
|
||||
a4: $ReadOnlyArray<T>,
|
||||
comparator?: Comparator<T>
|
||||
): Array<T>;
|
||||
uniq<T>(array?: ?Array<T>): Array<T>;
|
||||
|
@ -413,7 +413,7 @@ declare module "lodash" {
|
|||
uniqWith<T>(array?: ?Array<T>, comparator?: ?Comparator<T>): Array<T>;
|
||||
unzip<T>(array?: ?Array<T>): Array<T>;
|
||||
unzipWith<T>(array: ?Array<T>, iteratee?: ?Iteratee<T>): Array<T>;
|
||||
without<T>(array?: ?Array<T>, ...values?: Array<?T>): Array<T>;
|
||||
without<T>(array?: ?$ReadOnlyArray<T>, ...values?: Array<?T>): Array<T>;
|
||||
xor<T>(...array: Array<Array<T>>): Array<T>;
|
||||
//Workaround until (...parameter: T, parameter2: U) works
|
||||
xorBy<T>(a1?: ?Array<T>, iteratee?: ?ValueOnlyIteratee<T>): Array<T>;
|
||||
|
@ -512,16 +512,16 @@ declare module "lodash" {
|
|||
countBy<T>(array: void | null, iteratee?: ?ValueOnlyIteratee<T>): {};
|
||||
countBy<T: Object>(object: T, iteratee?: ?ValueOnlyIteratee<T>): Object;
|
||||
// alias of _.forEach
|
||||
each<T>(array: Array<T>, iteratee?: ?Iteratee<T>): Array<T>;
|
||||
each<T>(array: $ReadOnlyArray<T>, iteratee?: ?Iteratee<T>): Array<T>;
|
||||
each<T: void | null>(array: T, iteratee?: ?Iteratee<any>): T;
|
||||
each<T: Object>(object: T, iteratee?: ?OIteratee<T>): T;
|
||||
// alias of _.forEachRight
|
||||
eachRight<T>(array: Array<T>, iteratee?: ?Iteratee<T>): Array<T>;
|
||||
eachRight<T>(array: $ReadOnlyArray<T>, iteratee?: ?Iteratee<T>): Array<T>;
|
||||
eachRight<T: void | null>(array: T, iteratee?: ?Iteratee<any>): T;
|
||||
eachRight<T: Object>(object: T, iteratee?: OIteratee<T>): T;
|
||||
every<T>(array?: ?Array<T>, iteratee?: ?Iteratee<T>): boolean;
|
||||
every<T>(array?: ?$ReadOnlyArray<T>, iteratee?: ?Iteratee<T>): boolean;
|
||||
every<T: Object>(object: T, iteratee?: OIteratee<T>): boolean;
|
||||
filter<T>(array?: ?Array<T>, predicate?: ?Predicate<T>): Array<T>;
|
||||
filter<T>(array?: ?$ReadOnlyArray<T>, predicate?: ?Predicate<T>): Array<T>;
|
||||
filter<A, T: { [id: string]: A }>(
|
||||
object: T,
|
||||
predicate?: OPredicate<A, T>
|
||||
|
@ -550,13 +550,16 @@ declare module "lodash" {
|
|||
object: T,
|
||||
predicate?: ?OPredicate<A, T>
|
||||
): V;
|
||||
flatMap<T, U>(array?: ?Array<T>, iteratee?: ?FlatMapIteratee<T, U>): Array<U>;
|
||||
flatMap<T, U>(
|
||||
array?: ?$ReadOnlyArray<T>,
|
||||
iteratee?: ?FlatMapIteratee<T, U>
|
||||
): Array<U>;
|
||||
flatMap<T: Object, U>(
|
||||
object: T,
|
||||
iteratee?: OFlatMapIteratee<T, U>
|
||||
): Array<U>;
|
||||
flatMapDeep<T, U>(
|
||||
array?: ?Array<T>,
|
||||
array?: ?$ReadOnlyArray<T>,
|
||||
iteratee?: ?FlatMapIteratee<T, U>
|
||||
): Array<U>;
|
||||
flatMapDeep<T: Object, U>(
|
||||
|
@ -573,14 +576,14 @@ declare module "lodash" {
|
|||
iteratee?: OFlatMapIteratee<T, U>,
|
||||
depth?: number
|
||||
): Array<U>;
|
||||
forEach<T>(array: Array<T>, iteratee?: ?Iteratee<T>): Array<T>;
|
||||
forEach<T>(array: $ReadOnlyArray<T>, iteratee?: ?Iteratee<T>): Array<T>;
|
||||
forEach<T: void | null>(array: T, iteratee?: ?Iteratee<any>): T;
|
||||
forEach<T: Object>(object: T, iteratee?: ?OIteratee<T>): T;
|
||||
forEachRight<T>(array: Array<T>, iteratee?: ?Iteratee<T>): Array<T>;
|
||||
forEachRight<T>(array: $ReadOnlyArray<T>, iteratee?: ?Iteratee<T>): Array<T>;
|
||||
forEachRight<T: void | null>(array: T, iteratee?: ?Iteratee<any>): T;
|
||||
forEachRight<T: Object>(object: T, iteratee?: ?OIteratee<T>): T;
|
||||
groupBy<V, T>(
|
||||
array: Array<T>,
|
||||
array: $ReadOnlyArray<T>,
|
||||
iteratee?: ?ValueOnlyIteratee<T>
|
||||
): { [key: V]: Array<T> };
|
||||
groupBy(
|
||||
|
@ -591,12 +594,12 @@ declare module "lodash" {
|
|||
object: T,
|
||||
iteratee?: ValueOnlyIteratee<A>
|
||||
): { [key: V]: Array<A> };
|
||||
includes<T>(array: Array<T>, value: T, fromIndex?: ?number): boolean;
|
||||
includes<T>(array: $ReadOnlyArray<T>, value: T, fromIndex?: ?number): boolean;
|
||||
includes<T>(array: void | null, value?: ?T, fromIndex?: ?number): false;
|
||||
includes<T: Object>(object: T, value: any, fromIndex?: number): boolean;
|
||||
includes(str: string, value: string, fromIndex?: number): boolean;
|
||||
invokeMap<T>(
|
||||
array?: ?Array<T>,
|
||||
array?: ?$ReadOnlyArray<T>,
|
||||
path?: ?((value: T) => Array<string> | string) | Array<string> | string,
|
||||
...args?: Array<any>
|
||||
): Array<any>;
|
||||
|
@ -606,9 +609,9 @@ declare module "lodash" {
|
|||
...args?: Array<any>
|
||||
): Array<any>;
|
||||
keyBy<T, V>(
|
||||
array: Array<T>,
|
||||
array: $ReadOnlyArray<T>,
|
||||
iteratee?: ?ValueOnlyIteratee<T>
|
||||
): { [key: V]: ?T };
|
||||
): { [key: V]: T };
|
||||
keyBy(
|
||||
array: void | null,
|
||||
iteratee?: ?ValueOnlyIteratee<*>
|
||||
|
@ -616,7 +619,7 @@ declare module "lodash" {
|
|||
keyBy<V, A, I, T: { [id: I]: A }>(
|
||||
object: T,
|
||||
iteratee?: ?ValueOnlyIteratee<A>
|
||||
): { [key: V]: ?A };
|
||||
): { [key: V]: A };
|
||||
map<T, U>(array?: ?Array<T>, iteratee?: ?MapIterator<T, U>): Array<U>;
|
||||
map<T, U>(
|
||||
array: ?$ReadOnlyArray<T>,
|
||||
|
@ -631,19 +634,19 @@ declare module "lodash" {
|
|||
iteratee?: (char: string, index: number, str: string) => any
|
||||
): string;
|
||||
orderBy<T>(
|
||||
array: Array<T>,
|
||||
iteratees?: ?Array<Iteratee<T>> | ?string,
|
||||
orders?: ?Array<"asc" | "desc"> | ?string
|
||||
array: $ReadOnlyArray<T>,
|
||||
iteratees?: ?$ReadOnlyArray<Iteratee<T>> | ?string,
|
||||
orders?: ?$ReadOnlyArray<"asc" | "desc"> | ?string
|
||||
): Array<T>;
|
||||
orderBy<T>(
|
||||
array: null | void,
|
||||
iteratees?: ?Array<Iteratee<T>> | ?string,
|
||||
orders?: ?Array<"asc" | "desc"> | ?string
|
||||
array: null | void,
|
||||
iteratees?: ?$ReadOnlyArray<Iteratee<T>> | ?string,
|
||||
orders?: ?$ReadOnlyArray<"asc" | "desc"> | ?string
|
||||
): Array<T>;
|
||||
orderBy<V, T: Object>(
|
||||
object: T,
|
||||
iteratees?: Array<OIteratee<*>> | string,
|
||||
orders?: Array<"asc" | "desc"> | string
|
||||
iteratees?: $ReadOnlyArray<OIteratee<*>> | string,
|
||||
orders?: $ReadOnlyArray<"asc" | "desc"> | string
|
||||
): Array<V>;
|
||||
partition<T>(
|
||||
array?: ?Array<T>,
|
||||
|
@ -654,7 +657,7 @@ declare module "lodash" {
|
|||
predicate?: OPredicate<A, T>
|
||||
): [Array<V>, Array<V>];
|
||||
reduce<T, U>(
|
||||
array: Array<T>,
|
||||
array: $ReadOnlyArray<T>,
|
||||
iteratee?: (
|
||||
accumulator: U,
|
||||
value: T,
|
||||
|
@ -689,7 +692,7 @@ declare module "lodash" {
|
|||
accumulator?: ?U
|
||||
): void | null;
|
||||
reduceRight<T, U>(
|
||||
array: Array<T>,
|
||||
array: $ReadOnlyArray<T>,
|
||||
iteratee?: ?(
|
||||
accumulator: U,
|
||||
value: T,
|
||||
|
@ -703,7 +706,7 @@ declare module "lodash" {
|
|||
iteratee?: ?(accumulator: U, value: any, key: string, object: T) => U,
|
||||
accumulator?: ?U
|
||||
): U;
|
||||
reject<T>(array: ?Array<T>, predicate?: Predicate<T>): Array<T>;
|
||||
reject<T>(array: ?$ReadOnlyArray<T>, predicate?: Predicate<T>): Array<T>;
|
||||
reject<V: Object, A, T: { [id: string]: A }>(
|
||||
object?: ?T,
|
||||
predicate?: ?OPredicate<A, T>
|
||||
|
@ -714,20 +717,29 @@ declare module "lodash" {
|
|||
sampleSize<V, T: Object>(object: T, n?: number): Array<V>;
|
||||
shuffle<T>(array: ?Array<T>): Array<T>;
|
||||
shuffle<V, T: Object>(object: T): Array<V>;
|
||||
size(collection: Array<any> | Object | string): number;
|
||||
some<T>(array: ?Array<T>, predicate?: Predicate<T>): boolean;
|
||||
size(collection: $ReadOnlyArray<any> | Object | string): number;
|
||||
some<T>(array: ?$ReadOnlyArray<T>, predicate?: Predicate<T>): boolean;
|
||||
some<T>(array: void | null, predicate?: ?Predicate<T>): false;
|
||||
some<A, T: { [id: string]: A }>(
|
||||
object?: ?T,
|
||||
predicate?: OPredicate<A, T>
|
||||
): boolean;
|
||||
sortBy<T>(array: ?Array<T>, ...iteratees?: Array<Iteratee<T>>): Array<T>;
|
||||
sortBy<T>(array: ?Array<T>, iteratees?: Array<Iteratee<T>>): Array<T>;
|
||||
sortBy<T>(
|
||||
array: ?$ReadOnlyArray<T>,
|
||||
...iteratees?: $ReadOnlyArray<Iteratee<T>>
|
||||
): Array<T>;
|
||||
sortBy<T>(
|
||||
array: ?$ReadOnlyArray<T>,
|
||||
iteratees?: $ReadOnlyArray<Iteratee<T>>
|
||||
): Array<T>;
|
||||
sortBy<V, T: Object>(
|
||||
object: T,
|
||||
...iteratees?: Array<OIteratee<T>>
|
||||
): Array<V>;
|
||||
sortBy<V, T: Object>(object: T, iteratees?: Array<OIteratee<T>>): Array<V>;
|
||||
sortBy<V, T: Object>(
|
||||
object: T,
|
||||
iteratees?: $ReadOnlyArray<OIteratee<T>>
|
||||
): Array<V>;
|
||||
|
||||
// Date
|
||||
now(): number;
|
||||
|
@ -841,8 +853,8 @@ declare module "lodash" {
|
|||
source: U
|
||||
) => boolean | void
|
||||
): boolean;
|
||||
isNaN(value: Function | string | void | null | Object): false;
|
||||
isNaN(value: number): boolean;
|
||||
isNaN(value: any): false;
|
||||
isNative(value: number | string | void | null | Object): false;
|
||||
isNative(value: any): boolean;
|
||||
isNil(value: void | null): true;
|
||||
|
@ -864,9 +876,7 @@ declare module "lodash" {
|
|||
isSet(value: Set<any>): true;
|
||||
isSet(value: any): false;
|
||||
isString(value: string): true;
|
||||
isString(
|
||||
value: number | boolean | Function | void | null | Object | Array<any>
|
||||
): false;
|
||||
isString(value: any): false;
|
||||
isSymbol(value: Symbol): true;
|
||||
isSymbol(value: any): false;
|
||||
isTypedArray(value: $TypedArray): true;
|
||||
|
@ -900,11 +910,11 @@ declare module "lodash" {
|
|||
divide(dividend: number, divisor: number): number;
|
||||
floor(number: number, precision?: number): number;
|
||||
max<T>(array: ?Array<T>): T;
|
||||
maxBy<T>(array: ?Array<T>, iteratee?: Iteratee<T>): T;
|
||||
maxBy<T>(array: ?$ReadOnlyArray<T>, iteratee?: Iteratee<T>): T;
|
||||
mean(array: Array<*>): number;
|
||||
meanBy<T>(array: Array<T>, iteratee?: Iteratee<T>): number;
|
||||
min<T>(array: ?Array<T>): T;
|
||||
minBy<T>(array: ?Array<T>, iteratee?: Iteratee<T>): T;
|
||||
minBy<T>(array: ?$ReadOnlyArray<T>, iteratee?: Iteratee<T>): T;
|
||||
multiply(multiplier: number, multiplicand: number): number;
|
||||
round(number: number, precision?: number): number;
|
||||
subtract(minuend: number, subtrahend: number): number;
|
||||
|
@ -918,7 +928,7 @@ declare module "lodash" {
|
|||
random(lower?: number, upper?: number, floating?: boolean): number;
|
||||
|
||||
// Object
|
||||
assign(object?: ?Object, ...sources?: Array<Object>): Object;
|
||||
assign(object?: ?Object, ...sources?: Array<?Object>): Object;
|
||||
assignIn(): {};
|
||||
assignIn<A, B>(a: A, b: B): A & B;
|
||||
assignIn<A, B, C>(a: A, b: B, c: C): A & B & C;
|
||||
|
@ -1030,8 +1040,8 @@ declare module "lodash" {
|
|||
at(object?: ?Object, paths: Array<string>): Array<any>;
|
||||
create<T>(prototype: T, properties: Object): $Supertype<T>;
|
||||
create(prototype: any, properties: void | null): {};
|
||||
defaults(object?: ?Object, ...sources?: Array<Object>): Object;
|
||||
defaultsDeep(object?: ?Object, ...sources?: Array<Object>): Object;
|
||||
defaults(object?: ?Object, ...sources?: Array<?Object>): Object;
|
||||
defaultsDeep(object?: ?Object, ...sources?: Array<?Object>): Object;
|
||||
// alias for _.toPairs
|
||||
entries(object?: ?Object): Array<[string, any]>;
|
||||
// alias for _.toPairsIn
|
||||
|
@ -1119,8 +1129,8 @@ declare module "lodash" {
|
|||
functions(object?: ?Object): Array<string>;
|
||||
functionsIn(object?: ?Object): Array<string>;
|
||||
get(
|
||||
object?: ?Object | ?Array<any>,
|
||||
path?: ?Array<string> | string,
|
||||
object?: ?Object | ?$ReadOnlyArray<any> | void | null,
|
||||
path?: ?$ReadOnlyArray<string | number> | string | number,
|
||||
defaultValue?: any
|
||||
): any;
|
||||
has(object: Object, path: Array<string> | string): boolean;
|
||||
|
@ -1198,22 +1208,22 @@ declare module "lodash" {
|
|||
): Object;
|
||||
omit(object?: ?Object, ...props: Array<string>): Object;
|
||||
omit(object?: ?Object, props: Array<string>): Object;
|
||||
omitBy<A, T: { [id: string]: A }>(
|
||||
omitBy<A, T: { [id: string]: A }|{ [id: number]: A }>(
|
||||
object: T,
|
||||
predicate?: ?OPredicate<A, T>
|
||||
): Object;
|
||||
omitBy<A, T: void | null>(
|
||||
object: T,
|
||||
omitBy<A, T>(
|
||||
object: void | null,
|
||||
predicate?: ?OPredicate<A, T>
|
||||
): {};
|
||||
pick(object?: ?Object, ...props: Array<string>): Object;
|
||||
pick(object?: ?Object, props: Array<string>): Object;
|
||||
pickBy<A, T: { [id: string]: A }>(
|
||||
pickBy<A, T: { [id: string]: A }|{ [id: number]: A }>(
|
||||
object: T,
|
||||
predicate?: ?OPredicate<A, T>
|
||||
): Object;
|
||||
pickBy<A, T: void | null>(
|
||||
object: T,
|
||||
pickBy<A, T>(
|
||||
object: void | null,
|
||||
predicate?: ?OPredicate<A, T>
|
||||
): {};
|
||||
result(
|
||||
|
@ -1241,7 +1251,7 @@ declare module "lodash" {
|
|||
toPairs(object?: ?Object | Array<*>): Array<[string, any]>;
|
||||
toPairsIn(object?: ?Object): Array<[string, any]>;
|
||||
transform(
|
||||
collection: Object | Array<any>,
|
||||
collection: Object | $ReadOnlyArray<any>,
|
||||
iteratee?: ?OIteratee<*>,
|
||||
accumulator?: any
|
||||
): any;
|
||||
|
@ -1362,10 +1372,8 @@ declare module "lodash" {
|
|||
// NaN is a number instead of its own type, otherwise it would behave like null/void
|
||||
defaultTo<T1: number, T2>(value: T1, defaultValue: T2): T1 | T2;
|
||||
defaultTo<T1: void | null, T2>(value: T1, defaultValue: T2): T2;
|
||||
flow: $ComposeReverse;
|
||||
flow(funcs?: Array<Function>): Function;
|
||||
flowRight: $Compose;
|
||||
flowRight(funcs?: Array<Function>): Function;
|
||||
flow: ($ComposeReverse & (funcs: Array<Function>) => Function);
|
||||
flowRight: ($Compose & (funcs: Array<Function>) => Function);
|
||||
identity<T>(value: T): T;
|
||||
iteratee(func?: any): Function;
|
||||
matches(source?: ?Object): Function;
|
||||
|
@ -1612,7 +1620,7 @@ declare module "lodash/fp" {
|
|||
// Array
|
||||
chunk<T>(size: number): (array: Array<T>) => Array<Array<T>>;
|
||||
chunk<T>(size: number, array: Array<T>): Array<Array<T>>;
|
||||
compact<T, N: T>(array: Array<N>): Array<T>;
|
||||
compact<T, N: ?T>(array?: ?$ReadOnlyArray<N>): Array<T>;
|
||||
concat<T, U, A: Array<T> | T, B: Array<U> | U>(
|
||||
base: A
|
||||
): (elements: B) => Array<T | U>;
|
||||
|
@ -1620,30 +1628,34 @@ declare module "lodash/fp" {
|
|||
base: A,
|
||||
elements: B
|
||||
): Array<T | U>;
|
||||
difference<T>(values: Array<T>): (array: Array<T>) => Array<T>;
|
||||
difference<T>(values: Array<T>, array: Array<T>): Array<T>;
|
||||
difference<T>(values: $ReadOnlyArray<T>): (array: $ReadOnlyArray<T>) => T[];
|
||||
difference<T>(values: $ReadOnlyArray<T>, array: $ReadOnlyArray<T>): T[];
|
||||
differenceBy<T>(
|
||||
iteratee: ValueOnlyIteratee<T>
|
||||
): ((values: Array<T>) => (array: Array<T>) => T[]) &
|
||||
((values: Array<T>, array: Array<T>) => T[]);
|
||||
): ((values: $ReadOnlyArray<T>) => (array: $ReadOnlyArray<T>) => T[]) &
|
||||
((values: $ReadOnlyArray<T>, array: $ReadOnlyArray<T>) => T[]);
|
||||
differenceBy<T>(
|
||||
iteratee: ValueOnlyIteratee<T>,
|
||||
values: Array<T>
|
||||
): (array: Array<T>) => T[];
|
||||
values: $ReadOnlyArray<T>
|
||||
): (array: $ReadOnlyArray<T>) => T[];
|
||||
differenceBy<T>(
|
||||
iteratee: ValueOnlyIteratee<T>,
|
||||
values: Array<T>,
|
||||
array: Array<T>
|
||||
values: $ReadOnlyArray<T>,
|
||||
array: $ReadOnlyArray<T>
|
||||
): T[];
|
||||
differenceWith<T>(
|
||||
values: T[]
|
||||
): ((comparator: Comparator<T>) => (array: T[]) => T[]) &
|
||||
((comparator: Comparator<T>, array: T[]) => T[]);
|
||||
comparator: Comparator<T>,
|
||||
): ((first: $ReadOnly<T>) => (second: $ReadOnly<T>) => T[]) &
|
||||
((first: $ReadOnly<T>, second: $ReadOnly<T>) => T[]);
|
||||
differenceWith<T>(
|
||||
values: T[],
|
||||
comparator: Comparator<T>
|
||||
): (array: T[]) => T[];
|
||||
differenceWith<T>(values: T[], comparator: Comparator<T>, array: T[]): T[];
|
||||
comparator: Comparator<T>,
|
||||
first: $ReadOnly<T>,
|
||||
): (second: $ReadOnly<T>) => T[];
|
||||
differenceWith<T>(
|
||||
comparator: Comparator<T>,
|
||||
first: $ReadOnly<T>,
|
||||
second: $ReadOnly<T>
|
||||
): T[];
|
||||
drop<T>(n: number): (array: Array<T>) => Array<T>;
|
||||
drop<T>(n: number, array: Array<T>): Array<T>;
|
||||
dropLast<T>(n: number): (array: Array<T>) => Array<T>;
|
||||
|
@ -1713,14 +1725,14 @@ declare module "lodash/fp" {
|
|||
array: $ReadOnlyArray<T>
|
||||
): number;
|
||||
// alias of _.head
|
||||
first<T>(array: Array<T>): T;
|
||||
first<T>(array: $ReadOnlyArray<T>): T;
|
||||
flatten<T, X>(array: Array<Array<T> | X>): Array<T | X>;
|
||||
unnest<T, X>(array: Array<Array<T> | X>): Array<T | X>;
|
||||
flattenDeep<T>(array: any[]): Array<T>;
|
||||
flattenDepth(depth: number): (array: any[]) => any[];
|
||||
flattenDepth(depth: number, array: any[]): any[];
|
||||
fromPairs<A, B>(pairs: Array<[A, B]>): { [key: A]: B };
|
||||
head<T>(array: Array<T>): T;
|
||||
head<T>(array: $ReadOnlyArray<T>): T;
|
||||
indexOf<T>(value: T): (array: Array<T>) => number;
|
||||
indexOf<T>(value: T, array: Array<T>): number;
|
||||
indexOfFrom<T>(
|
||||
|
@ -1984,25 +1996,25 @@ declare module "lodash/fp" {
|
|||
// alias of _.forEach
|
||||
each<T>(
|
||||
iteratee: Iteratee<T> | OIteratee<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => Array<T>;
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => Array<T>;
|
||||
each<T>(
|
||||
iteratee: Iteratee<T> | OIteratee<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): Array<T>;
|
||||
// alias of _.forEachRight
|
||||
eachRight<T>(
|
||||
iteratee: Iteratee<T> | OIteratee<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => Array<T>;
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => Array<T>;
|
||||
eachRight<T>(
|
||||
iteratee: Iteratee<T> | OIteratee<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): Array<T>;
|
||||
every<T>(
|
||||
iteratee: Iteratee<T> | OIteratee<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => boolean;
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => boolean;
|
||||
every<T>(
|
||||
iteratee: Iteratee<T> | OIteratee<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): boolean;
|
||||
all<T>(
|
||||
iteratee: Iteratee<T> | OIteratee<T>
|
||||
|
@ -2013,10 +2025,10 @@ declare module "lodash/fp" {
|
|||
): boolean;
|
||||
filter<T>(
|
||||
predicate: Predicate<T> | OPredicate<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => Array<T>;
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => Array<T>;
|
||||
filter<T>(
|
||||
predicate: Predicate<T> | OPredicate<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): Array<T>;
|
||||
find<T>(
|
||||
predicate: Predicate<T> | OPredicate<T>
|
||||
|
@ -2099,29 +2111,31 @@ declare module "lodash/fp" {
|
|||
): Array<U>;
|
||||
forEach<T>(
|
||||
iteratee: Iteratee<T> | OIteratee<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => Array<T>;
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => Array<T>;
|
||||
forEach<T>(
|
||||
iteratee: Iteratee<T> | OIteratee<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): Array<T>;
|
||||
forEachRight<T>(
|
||||
iteratee: Iteratee<T> | OIteratee<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => Array<T>;
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => Array<T>;
|
||||
forEachRight<T>(
|
||||
iteratee: Iteratee<T> | OIteratee<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): Array<T>;
|
||||
groupBy<V, T>(
|
||||
iteratee: ValueOnlyIteratee<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => { [key: V]: Array<T> };
|
||||
): (
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
) => { [key: V]: Array<T> };
|
||||
groupBy<V, T>(
|
||||
iteratee: ValueOnlyIteratee<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): { [key: V]: Array<T> };
|
||||
includes(value: string): (str: string) => boolean;
|
||||
includes(value: string, str: string): boolean;
|
||||
includes<T>(value: T): (collection: Array<T> | { [id: any]: T }) => boolean;
|
||||
includes<T>(value: T, collection: Array<T> | { [id: any]: T }): boolean;
|
||||
includes(value: string): (str: string) => boolean;
|
||||
includes(value: string, str: string): boolean;
|
||||
contains(value: string): (str: string) => boolean;
|
||||
contains(value: string, str: string): boolean;
|
||||
contains<T>(value: T): (collection: Array<T> | { [id: any]: T }) => boolean;
|
||||
|
@ -2168,24 +2182,24 @@ declare module "lodash/fp" {
|
|||
): Array<any>;
|
||||
keyBy<T, V>(
|
||||
iteratee: ValueOnlyIteratee<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => { [key: V]: T };
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => { [key: V]: T };
|
||||
keyBy<T, V>(
|
||||
iteratee: ValueOnlyIteratee<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): { [key: V]: T };
|
||||
indexBy<T, V>(
|
||||
iteratee: ValueOnlyIteratee<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => { [key: V]: T };
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => { [key: V]: T };
|
||||
indexBy<T, V>(
|
||||
iteratee: ValueOnlyIteratee<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): { [key: V]: T };
|
||||
map<T, U>(
|
||||
iteratee: MapIterator<T, U> | OMapIterator<T, U>
|
||||
): (collection: Array<T> | { [id: any]: T }) => Array<U>;
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => Array<U>;
|
||||
map<T, U>(
|
||||
iteratee: MapIterator<T, U> | OMapIterator<T, U>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): Array<U>;
|
||||
map(iteratee: (char: string) => any): (str: string) => string;
|
||||
map(iteratee: (char: string) => any, str: string): string;
|
||||
|
@ -2199,22 +2213,22 @@ declare module "lodash/fp" {
|
|||
pluck(iteratee: (char: string) => any): (str: string) => string;
|
||||
pluck(iteratee: (char: string) => any, str: string): string;
|
||||
orderBy<T>(
|
||||
iteratees: Array<Iteratee<T> | OIteratee<*>> | string
|
||||
iteratees: $ReadOnlyArray<Iteratee<T> | OIteratee<*>> | string
|
||||
): ((
|
||||
orders: Array<"asc" | "desc"> | string
|
||||
) => (collection: Array<T> | { [id: any]: T }) => Array<T>) &
|
||||
orders: $ReadOnlyArray<"asc" | "desc"> | string
|
||||
) => (collection: $ReadOnlyArray<T> | { [id: any]: T }) => Array<T>) &
|
||||
((
|
||||
orders: Array<"asc" | "desc"> | string,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
orders: $ReadOnlyArray<"asc" | "desc"> | string,
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
) => Array<T>);
|
||||
orderBy<T>(
|
||||
iteratees: Array<Iteratee<T> | OIteratee<*>> | string,
|
||||
orders: Array<"asc" | "desc"> | string
|
||||
): (collection: Array<T> | { [id: any]: T }) => Array<T>;
|
||||
iteratees: $ReadOnlyArray<Iteratee<T> | OIteratee<*>> | string,
|
||||
orders: $ReadOnlyArray<"asc" | "desc"> | string
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => Array<T>;
|
||||
orderBy<T>(
|
||||
iteratees: Array<Iteratee<T> | OIteratee<*>> | string,
|
||||
orders: Array<"asc" | "desc"> | string,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
iteratees: $ReadOnlyArray<Iteratee<T> | OIteratee<*>> | string,
|
||||
orders: $ReadOnlyArray<"asc" | "desc"> | string,
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): Array<T>;
|
||||
partition<T>(
|
||||
predicate: Predicate<T> | OPredicate<T>
|
||||
|
@ -2262,27 +2276,31 @@ declare module "lodash/fp" {
|
|||
): (collection: Array<T> | { [id: any]: T }) => Array<T>;
|
||||
sampleSize<T>(n: number, collection: Array<T> | { [id: any]: T }): Array<T>;
|
||||
shuffle<T>(collection: Array<T> | { [id: any]: T }): Array<T>;
|
||||
size(collection: Array<any> | Object | string): number;
|
||||
size(collection: $ReadOnlyArray<any> | Object | string): number;
|
||||
some<T>(
|
||||
predicate: Predicate<T> | OPredicate<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => boolean;
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => boolean;
|
||||
some<T>(
|
||||
predicate: Predicate<T> | OPredicate<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): boolean;
|
||||
any<T>(
|
||||
predicate: Predicate<T> | OPredicate<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => boolean;
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => boolean;
|
||||
any<T>(
|
||||
predicate: Predicate<T> | OPredicate<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T }
|
||||
): boolean;
|
||||
sortBy<T>(
|
||||
iteratees: Array<Iteratee<T> | OIteratee<T>> | Iteratee<T> | OIteratee<T>
|
||||
): (collection: Array<T> | { [id: any]: T }) => Array<T>;
|
||||
iteratees: | $ReadOnlyArray<Iteratee<T> | OIteratee<T>>
|
||||
| Iteratee<T>
|
||||
| OIteratee<T>
|
||||
): (collection: $ReadOnlyArray<T> | { [id: any]: T }) => Array<T>;
|
||||
sortBy<T>(
|
||||
iteratees: Array<Iteratee<T> | OIteratee<T>> | Iteratee<T> | OIteratee<T>,
|
||||
collection: Array<T> | { [id: any]: T }
|
||||
iteratees: | $ReadOnlyArray<Iteratee<T> | OIteratee<T>>
|
||||
| Iteratee<T>
|
||||
| OIteratee<T>,
|
||||
collection: $ReadOnlyArray<T> | { [id: any]: T },
|
||||
): Array<T>;
|
||||
|
||||
// Date
|
||||
|
@ -2489,9 +2507,7 @@ declare module "lodash/fp" {
|
|||
isSafeInteger(value: any): boolean;
|
||||
isSet(value: any): boolean;
|
||||
isString(value: string): true;
|
||||
isString(
|
||||
value: number | boolean | Function | void | null | Object | Array<any>
|
||||
): false;
|
||||
isString(value: any): false;
|
||||
isSymbol(value: any): boolean;
|
||||
isTypedArray(value: any): boolean;
|
||||
isUndefined(value: any): boolean;
|
||||
|
@ -2751,8 +2767,8 @@ declare module "lodash/fp" {
|
|||
forOwnRight(iteratee: OIteratee<*>, object: Object): Object;
|
||||
functions(object: Object): Array<string>;
|
||||
functionsIn(object: Object): Array<string>;
|
||||
get(path: Array<string> | string): (object: Object | Array<any>) => any;
|
||||
get(path: Array<string> | string, object: Object | Array<any>): any;
|
||||
get(path: $ReadOnlyArray<string | number> | string | number): (object: Object | $ReadOnlyArray<any> | void | null) => any;
|
||||
get(path: $ReadOnlyArray<string | number> | string | number, object: Object | $ReadOnlyArray<any> | void | null): any;
|
||||
prop(path: Array<string> | string): (object: Object | Array<any>) => any;
|
||||
prop(path: Array<string> | string, object: Object | Array<any>): any;
|
||||
path(path: Array<string> | string): (object: Object | Array<any>) => any;
|
||||
|
@ -2762,15 +2778,15 @@ declare module "lodash/fp" {
|
|||
): ((
|
||||
path: Array<string> | string
|
||||
) => (object: Object | Array<any>) => any) &
|
||||
((path: Array<string> | string, object: Object | Array<any>) => any);
|
||||
((path: Array<string> | string, object: Object | $ReadOnlyArray<any> | void | null) => any);
|
||||
getOr(
|
||||
defaultValue: any,
|
||||
path: Array<string> | string
|
||||
): (object: Object | Array<any>) => any;
|
||||
): (object: Object | $ReadOnlyArray<any> | void | null) => any;
|
||||
getOr(
|
||||
defaultValue: any,
|
||||
path: Array<string> | string,
|
||||
object: Object | Array<any>
|
||||
object: Object | $ReadOnlyArray<any> | void | null
|
||||
): any;
|
||||
propOr(
|
||||
defaultValue: any
|
||||
|
@ -2951,23 +2967,25 @@ declare module "lodash/fp" {
|
|||
toPairsIn(object: Object): Array<[string, any]>;
|
||||
transform(
|
||||
iteratee: OIteratee<*>
|
||||
): ((accumulator: any) => (collection: Object | Array<any>) => any) &
|
||||
((accumulator: any, collection: Object | Array<any>) => any);
|
||||
): ((
|
||||
accumulator: any
|
||||
) => (collection: Object | $ReadOnlyArray<any>) => any) &
|
||||
((accumulator: any, collection: Object | $ReadOnlyArray<any>) => any);
|
||||
transform(
|
||||
iteratee: OIteratee<*>,
|
||||
accumulator: any
|
||||
): (collection: Object | Array<any>) => any;
|
||||
): (collection: Object | $ReadOnlyArray<any>) => any;
|
||||
transform(
|
||||
iteratee: OIteratee<*>,
|
||||
accumulator: any,
|
||||
collection: Object | Array<any>
|
||||
collection: Object | $ReadOnlyArray<any>
|
||||
): any;
|
||||
unset(path: Array<string> | string): (object: Object) => boolean;
|
||||
unset(path: Array<string> | string, object: Object): boolean;
|
||||
dissoc(path: Array<string> | string): (object: Object) => boolean;
|
||||
dissoc(path: Array<string> | string, object: Object): boolean;
|
||||
dissocPath(path: Array<string> | string): (object: Object) => boolean;
|
||||
dissocPath(path: Array<string> | string, object: Object): boolean;
|
||||
unset(path: Array<string> | string): (object: Object) => Object;
|
||||
unset(path: Array<string> | string, object: Object): Object;
|
||||
dissoc(path: Array<string> | string): (object: Object) => Object;
|
||||
dissoc(path: Array<string> | string, object: Object): Object;
|
||||
dissocPath(path: Array<string> | string): (object: Object) => Object;
|
||||
dissocPath(path: Array<string> | string, object: Object): Object;
|
||||
update(
|
||||
path: string[] | string
|
||||
): ((updater: Function) => (object: Object) => Object) &
|
||||
|
@ -3113,13 +3131,10 @@ declare module "lodash/fp" {
|
|||
defaultTo<T1: number, T2>(defaultValue: T2, value: T1): T1 | T2;
|
||||
defaultTo<T1: void | null, T2>(defaultValue: T2): (value: T1) => T2;
|
||||
defaultTo<T1: void | null, T2>(defaultValue: T2, value: T1): T2;
|
||||
flow: $ComposeReverse;
|
||||
flow(funcs: Array<Function>): Function;
|
||||
pipe: $ComposeReverse;
|
||||
pipe(funcs: Array<Function>): Function;
|
||||
flowRight: $Compose;
|
||||
flowRight(funcs: Array<Function>): Function;
|
||||
compose: $Compose;
|
||||
flow: ($ComposeReverse & (funcs: Array<Function>) => Function);
|
||||
pipe: ($ComposeReverse & (funcs: Array<Function>) => Function);
|
||||
flowRight: ($Compose & (funcs: Array<Function>) => Function);
|
||||
compose: ($Compose & (funcs: Array<Function>) => Function);
|
||||
compose(funcs: Array<Function>): Function;
|
||||
identity<T>(value: T): T;
|
||||
iteratee(func: any): Function;
|
||||
|
|
|
@ -37,6 +37,7 @@ module.exports = {
|
|||
coveragePathIgnorePatterns: [
|
||||
'node_modules',
|
||||
'fixtures',
|
||||
'<rootDir>/src/api/debug',
|
||||
'<rootDir>/test',
|
||||
],
|
||||
moduleNameMapper: {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
import {
|
||||
validateName as utilValidateName,
|
||||
validatePackage as utilValidatePackage,
|
||||
|
@ -115,7 +116,7 @@ export function allow(auth: IAuth) {
|
|||
} else {
|
||||
// last plugin (that's our built-in one) returns either
|
||||
// cb(err) or cb(null, true), so this should never happen
|
||||
throw ErrorCode.getInternalError('bug in the auth plugin system');
|
||||
throw ErrorCode.getInternalError(API_ERROR.PLUGIN_ERROR);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -123,15 +124,15 @@ export function allow(auth: IAuth) {
|
|||
}
|
||||
|
||||
export function final(body: any, req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
|
||||
if (res.statusCode === HTTP_STATUS.UNAUTHORIZED && !res.getHeader('WWW-Authenticate')) {
|
||||
if (res.statusCode === HTTP_STATUS.UNAUTHORIZED && !res.getHeader(HEADERS.WWW_AUTH)) {
|
||||
// they say it's required for 401, so...
|
||||
res.header('WWW-Authenticate', `${TOKEN_BASIC}, ${TOKEN_BEARER}`);
|
||||
res.header(HEADERS.WWW_AUTH, `${TOKEN_BASIC}, ${TOKEN_BEARER}`);
|
||||
}
|
||||
|
||||
try {
|
||||
if (_.isString(body) || _.isObject(body)) {
|
||||
if (!res.getHeader('Content-type')) {
|
||||
res.header('Content-type', HEADERS.JSON);
|
||||
if (!res.getHeader(HEADERS.CONTENT_TYPE)) {
|
||||
res.header(HEADERS.CONTENT_TYPE, HEADERS.JSON);
|
||||
}
|
||||
|
||||
if (typeof(body) === 'object' && _.isNil(body) === false) {
|
||||
|
@ -143,7 +144,7 @@ export function allow(auth: IAuth) {
|
|||
|
||||
// don't send etags with errors
|
||||
if (!res.statusCode || (res.statusCode >= 200 && res.statusCode < 300)) {
|
||||
res.header('ETag', '"' + stringToMD5(body) + '"');
|
||||
res.header(HEADERS.ETAG, '"' + stringToMD5(body) + '"');
|
||||
}
|
||||
} else {
|
||||
// send(null), send(204), etc.
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// @flow
|
||||
|
||||
import {assign, isObject, isFunction} from 'lodash';
|
||||
import Path from 'path';
|
||||
import URL from 'url';
|
||||
import fs from 'fs';
|
||||
import http from 'http';
|
||||
|
@ -9,53 +8,14 @@ import https from 'https';
|
|||
// $FlowFixMe
|
||||
import constants from 'constants';
|
||||
import endPointAPI from '../api/index';
|
||||
import {parseAddress} from './utils';
|
||||
import {getListListenAddresses, resolveConfigPath} from './cli/utils';
|
||||
import {API_ERROR, certPem, csrPem, keyPem} from './constants';
|
||||
|
||||
import type {Callback} from '@verdaccio/types';
|
||||
import type {$Application} from 'express';
|
||||
import {DEFAULT_PORT} from './constants';
|
||||
|
||||
const logger = require('./logger');
|
||||
|
||||
/**
|
||||
* Retrieve all addresses defined in the config file.
|
||||
* Verdaccio is able to listen multiple ports
|
||||
* @param {String} argListen
|
||||
* @param {String} configListen
|
||||
* eg:
|
||||
* listen:
|
||||
- localhost:5555
|
||||
- localhost:5557
|
||||
@return {Array}
|
||||
*/
|
||||
export function getListListenAddresses(argListen: string, configListen: mixed) {
|
||||
// command line || config file || default
|
||||
let addresses;
|
||||
if (argListen) {
|
||||
addresses = [argListen];
|
||||
} else if (Array.isArray(configListen)) {
|
||||
addresses = configListen;
|
||||
} else if (configListen) {
|
||||
addresses = [configListen];
|
||||
} else {
|
||||
addresses = [DEFAULT_PORT];
|
||||
}
|
||||
addresses = addresses.map(function(addr) {
|
||||
const parsedAddr = parseAddress(addr);
|
||||
|
||||
if (!parsedAddr) {
|
||||
logger.logger.warn({addr: addr},
|
||||
'invalid address - @{addr}, we expect a port (e.g. "4873"),'
|
||||
+ ' host:port (e.g. "localhost:4873") or full url'
|
||||
+ ' (e.g. "http://localhost:4873/")');
|
||||
}
|
||||
|
||||
return parsedAddr;
|
||||
}).filter(Boolean);
|
||||
|
||||
return addresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the server after configuration has been loaded.
|
||||
* @param {Object} config
|
||||
|
@ -71,7 +31,7 @@ function startVerdaccio(config: any,
|
|||
pkgName: string,
|
||||
callback: Callback) {
|
||||
if (isObject(config) === false) {
|
||||
throw new Error('config file must be an object');
|
||||
throw new Error(API_ERROR.CONFIG_BAD_FORMAT);
|
||||
}
|
||||
|
||||
endPointAPI(config).then((app)=> {
|
||||
|
@ -82,7 +42,7 @@ function startVerdaccio(config: any,
|
|||
if (addr.proto === 'https') {
|
||||
// https must either have key cert and ca or a pfx and (optionally) a passphrase
|
||||
if (!config.https || !config.https.key || !config.https.cert || !config.https.ca) {
|
||||
displayHTTPSWarning(configPath);
|
||||
logHTTPSWarning(configPath);
|
||||
}
|
||||
|
||||
webServer = handleHTTPS(app, configPath, config);
|
||||
|
@ -103,11 +63,7 @@ function unlinkAddressPath(addr) {
|
|||
}
|
||||
}
|
||||
|
||||
function displayHTTPSWarning(storageLocation) {
|
||||
const resolveConfigPath = function(file) {
|
||||
return Path.resolve(Path.dirname(storageLocation), file);
|
||||
};
|
||||
|
||||
function logHTTPSWarning(storageLocation) {
|
||||
logger.logger.fatal([
|
||||
'You have enabled HTTPS and need to specify either ',
|
||||
' "https.key", "https.cert" and "https.ca" or ',
|
||||
|
@ -116,16 +72,16 @@ function displayHTTPSWarning(storageLocation) {
|
|||
'',
|
||||
// commands are borrowed from node.js docs
|
||||
'To quickly create self-signed certificate, use:',
|
||||
' $ openssl genrsa -out ' + resolveConfigPath('verdaccio-key.pem') + ' 2048',
|
||||
' $ openssl req -new -sha256 -key ' + resolveConfigPath('verdaccio-key.pem') + ' -out ' + resolveConfigPath('verdaccio-csr.pem'),
|
||||
' $ openssl x509 -req -in ' + resolveConfigPath('verdaccio-csr.pem') +
|
||||
' -signkey ' + resolveConfigPath('verdaccio-key.pem') + ' -out ' + resolveConfigPath('verdaccio-cert.pem'),
|
||||
' $ openssl genrsa -out ' + resolveConfigPath(storageLocation, keyPem) + ' 2048',
|
||||
' $ openssl req -new -sha256 -key ' + resolveConfigPath(storageLocation, keyPem) + ' -out ' + resolveConfigPath(storageLocation, csrPem),
|
||||
' $ openssl x509 -req -in ' + resolveConfigPath(storageLocation, csrPem) +
|
||||
' -signkey ' + resolveConfigPath(storageLocation, keyPem) + ' -out ' + resolveConfigPath(storageLocation, certPem),
|
||||
'',
|
||||
'And then add to config file (' + storageLocation + '):',
|
||||
' https:',
|
||||
` key: ${resolveConfigPath('verdaccio-key.pem')}`,
|
||||
` cert: ${resolveConfigPath('verdaccio-cert.pem')}`,
|
||||
` ca: ${resolveConfigPath('verdaccio-csr.pem')}`,
|
||||
` key: ${resolveConfigPath(storageLocation, keyPem)}`,
|
||||
` cert: ${resolveConfigPath(storageLocation, certPem)}`,
|
||||
` ca: ${resolveConfigPath(storageLocation, csrPem)}`,
|
||||
].join('\n'));
|
||||
process.exit(2);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// @flow
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import {parseAddress} from '../utils';
|
||||
import {DEFAULT_PORT} from '../constants';
|
||||
|
||||
const logger = require('../logger');
|
||||
|
||||
export const resolveConfigPath = function(storageLocation: string, file: string) {
|
||||
return path.resolve(path.dirname(storageLocation), file);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve all addresses defined in the config file.
|
||||
* Verdaccio is able to listen multiple ports
|
||||
* @param {String} argListen
|
||||
* @param {String} configListen
|
||||
* eg:
|
||||
* listen:
|
||||
- localhost:5555
|
||||
- localhost:5557
|
||||
@return {Array}
|
||||
*/
|
||||
export function getListListenAddresses(argListen: string, configListen: mixed) {
|
||||
// command line || config file || default
|
||||
let addresses;
|
||||
if (argListen) {
|
||||
addresses = [argListen];
|
||||
} else if (Array.isArray(configListen)) {
|
||||
addresses = configListen;
|
||||
} else if (configListen) {
|
||||
addresses = [configListen];
|
||||
} else {
|
||||
addresses = [DEFAULT_PORT];
|
||||
}
|
||||
addresses = addresses.map(function(addr) {
|
||||
const parsedAddr = parseAddress(addr);
|
||||
|
||||
if (!parsedAddr) {
|
||||
logger.logger.warn({addr: addr},
|
||||
'invalid address - @{addr}, we expect a port (e.g. "4873"),'
|
||||
+ ' host:port (e.g. "localhost:4873") or full url'
|
||||
+ ' (e.g. "http://localhost:4873/")');
|
||||
}
|
||||
|
||||
return parsedAddr;
|
||||
}).filter(Boolean);
|
||||
|
||||
return addresses;
|
||||
}
|
|
@ -1,15 +1,24 @@
|
|||
// @flow
|
||||
|
||||
export const DEFAULT_PORT: string = '4873';
|
||||
export const DEFAULT_PROTOCOL: string = 'http';
|
||||
export const DEFAULT_DOMAIN: string = 'localhost';
|
||||
export const TIME_EXPIRATION_24H: string ='24h';
|
||||
export const TIME_EXPIRATION_7D: string = '7d';
|
||||
export const DIST_TAGS = 'dist-tags';
|
||||
|
||||
export const keyPem = 'verdaccio-key.pem';
|
||||
export const certPem = 'verdaccio-cert.pem';
|
||||
export const csrPem = 'verdaccio-csr.pem';
|
||||
|
||||
export const HEADERS = {
|
||||
JSON: 'application/json',
|
||||
CONTENT_TYPE: 'Content-type',
|
||||
ETAG: 'ETag',
|
||||
JSON_CHARSET: 'application/json; charset=utf-8',
|
||||
OCTET_STREAM: 'application/octet-stream; charset=utf-8',
|
||||
TEXT_CHARSET: 'text/plain; charset=utf-8',
|
||||
WWW_AUTH: 'WWW-Authenticate',
|
||||
GZIP: 'gzip',
|
||||
};
|
||||
|
||||
|
@ -73,8 +82,11 @@ export const API_MESSAGE = {
|
|||
};
|
||||
|
||||
export const API_ERROR = {
|
||||
PLUGIN_ERROR: 'bug in the auth plugin system',
|
||||
CONFIG_BAD_FORMAT: 'config file must be an object',
|
||||
BAD_USERNAME_PASSWORD: 'bad username/password, access denied',
|
||||
NO_PACKAGE: 'no such package available',
|
||||
BAD_DATA: 'bad data',
|
||||
NOT_ALLOWED: 'not allowed to access package',
|
||||
INTERNAL_SERVER_ERROR: 'internal server error',
|
||||
UNKNOWN_ERROR: 'unknown error',
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import Handlebars from 'handlebars';
|
||||
import request from 'request';
|
||||
import _ from 'lodash';
|
||||
import logger from './logger';
|
||||
|
||||
const handleNotify = function(metadata, notifyEntry, publisherInfo, publishedPackage) {
|
||||
import {notifyRequest} from './notify-request';
|
||||
|
||||
export function handleNotify(metadata, notifyEntry, publisherInfo, publishedPackage) {
|
||||
let regex;
|
||||
if (metadata.name && notifyEntry.packagePattern) {
|
||||
// FUTURE: comment out due https://github.com/verdaccio/verdaccio/pull/108#issuecomment-312421052
|
||||
// regex = new RegExp(notifyEntry.packagePattern, notifyEntry.packagePatternFlags || '');
|
||||
regex = new RegExp(notifyEntry.packagePattern);
|
||||
regex = new RegExp(notifyEntry.packagePattern, notifyEntry.packagePatternFlags || '');
|
||||
if (!regex.test(metadata.name)) {
|
||||
return;
|
||||
}
|
||||
|
@ -49,33 +47,14 @@ const handleNotify = function(metadata, notifyEntry, publisherInfo, publishedPac
|
|||
options.url = notifyEntry.endpoint;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
request(options, function(err, response, body) {
|
||||
if (err || response.statusCode >= 400) {
|
||||
const errorMessage = _.isNil(err) ? response.body : err.message;
|
||||
logger.logger.error({errorMessage}, 'notify service has thrown an error: @{errorMessage}');
|
||||
|
||||
reject(errorMessage);
|
||||
} else {
|
||||
logger.logger.info({content}, 'A notification has been shipped: @{content}');
|
||||
if (_.isNil(body) === false) {
|
||||
const bodyResolved = _.isNil(body) === false ? body : null;
|
||||
|
||||
logger.logger.debug({body}, ' body: @{body}');
|
||||
return resolve(bodyResolved);
|
||||
return notifyRequest(options, content);
|
||||
}
|
||||
|
||||
reject(Error('body is missing'));
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function sendNotification(metadata, key, ...moreMedatata) {
|
||||
export function sendNotification(metadata, key, ...moreMedatata) {
|
||||
return handleNotify(metadata, key, ...moreMedatata);
|
||||
}
|
||||
|
||||
const notify = function(metadata, config, ...moreMedatata) {
|
||||
export function notify(metadata, config, ...moreMedatata) {
|
||||
if (config.notify) {
|
||||
if (config.notify.content) {
|
||||
return sendNotification(metadata, config.notify, ...moreMedatata);
|
||||
|
@ -86,6 +65,4 @@ const notify = function(metadata, config, ...moreMedatata) {
|
|||
}
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
export {notify};
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import isNil from 'lodash/isNil';
|
||||
import logger from '../logger';
|
||||
import request from 'request';
|
||||
import {HTTP_STATUS} from '../constants';
|
||||
|
||||
export function notifyRequest(options, content) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request(options, function(err, response, body) {
|
||||
if (err || response.statusCode >= HTTP_STATUS.BAD_REQUEST) {
|
||||
const errorMessage = isNil(err) ? response.body : err.message;
|
||||
logger.logger.error({errorMessage}, 'notify service has thrown an error: @{errorMessage}');
|
||||
|
||||
reject(errorMessage);
|
||||
} else {
|
||||
logger.logger.info({content}, 'A notification has been shipped: @{content}');
|
||||
if (isNil(body) === false) {
|
||||
const bodyResolved = isNil(body) === false ? body : null;
|
||||
|
||||
logger.logger.debug({body}, ' body: @{body}');
|
||||
return resolve(bodyResolved);
|
||||
}
|
||||
|
||||
reject(Error('body is missing'));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
|
@ -14,6 +14,7 @@ import {
|
|||
API_ERROR,
|
||||
DEFAULT_PORT,
|
||||
DEFAULT_DOMAIN,
|
||||
DEFAULT_PROTOCOL,
|
||||
CHARACTER_ENCODING
|
||||
} from './constants';
|
||||
import {generateGravatarUrl} from '../utils/user';
|
||||
|
@ -67,17 +68,18 @@ export function validateName(name: string): boolean {
|
|||
if (_.isString(name) === false) {
|
||||
return false;
|
||||
}
|
||||
name = name.toLowerCase();
|
||||
|
||||
const normalizedName: string = name.toLowerCase();
|
||||
|
||||
// all URL-safe characters and "@" for issue #75
|
||||
return !(
|
||||
!name.match(/^[-a-zA-Z0-9_.!~*'()@]+$/) ||
|
||||
name.charAt(0) === '.' || // ".bin", etc.
|
||||
name.charAt(0) === '-' || // "-" is reserved by couchdb
|
||||
name === 'node_modules' ||
|
||||
name === '__proto__' ||
|
||||
name === 'package.json' ||
|
||||
name === 'favicon.ico'
|
||||
!normalizedName.match(/^[-a-zA-Z0-9_.!~*'()@]+$/) ||
|
||||
normalizedName.charAt(0) === '.' || // ".bin", etc.
|
||||
normalizedName.charAt(0) === '-' || // "-" is reserved by couchdb
|
||||
normalizedName === 'node_modules' ||
|
||||
normalizedName === '__proto__' ||
|
||||
normalizedName === 'package.json' ||
|
||||
normalizedName === 'favicon.ico'
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -221,7 +223,7 @@ export function tagVersion(data: Package, version: string, tag: StringValue): bo
|
|||
*/
|
||||
export function getVersion(pkg: Package, version: any) {
|
||||
// this condition must allow cast
|
||||
if (pkg.versions[version] != null) {
|
||||
if (_.isNil(pkg.versions[version]) === false) {
|
||||
return pkg.versions[version];
|
||||
}
|
||||
|
||||
|
@ -263,7 +265,7 @@ export function parseAddress(urlAddress: any) {
|
|||
|
||||
if (urlPattern) {
|
||||
return {
|
||||
proto: urlPattern[2] || 'http',
|
||||
proto: urlPattern[2] || DEFAULT_PROTOCOL,
|
||||
host: urlPattern[6] || urlPattern[7] || DEFAULT_DOMAIN,
|
||||
port: urlPattern[8] || DEFAULT_PORT,
|
||||
};
|
||||
|
@ -273,7 +275,7 @@ export function parseAddress(urlAddress: any) {
|
|||
|
||||
if (urlPattern) {
|
||||
return {
|
||||
proto: urlPattern[2] || 'http',
|
||||
proto: urlPattern[2] || DEFAULT_PROTOCOL,
|
||||
path: urlPattern[4],
|
||||
};
|
||||
}
|
||||
|
@ -391,7 +393,7 @@ export const ErrorCode = {
|
|||
return createError(HTTP_STATUS.CONFLICT, message);
|
||||
},
|
||||
getBadData: (customMessage?: string) => {
|
||||
return createError(HTTP_STATUS.BAD_DATA, customMessage || 'bad data');
|
||||
return createError(HTTP_STATUS.BAD_DATA, customMessage || API_ERROR.BAD_DATA);
|
||||
},
|
||||
getBadRequest: (customMessage?: string) => {
|
||||
return createError(HTTP_STATUS.BAD_REQUEST, customMessage);
|
||||
|
|
|
@ -59,31 +59,34 @@ export default function(server) {
|
|||
const testOnlyTest = 'test-only-test';
|
||||
const testOnlyAuth = 'test-only-auth';
|
||||
|
||||
// all are allowed to access
|
||||
describe('all are allowed to access', () => {
|
||||
checkAccess(validCredentials, testAccessOnly, true);
|
||||
checkAccess(undefined, testAccessOnly, true);
|
||||
checkAccess(badCredentials, testAccessOnly, true);
|
||||
checkPublish(validCredentials, testAccessOnly, false);
|
||||
checkPublish(undefined, testAccessOnly, false);
|
||||
checkPublish(badCredentials, testAccessOnly, false);
|
||||
});
|
||||
|
||||
// all are allowed to publish
|
||||
describe('all are allowed to publish', () => {
|
||||
checkAccess(validCredentials, testPublishOnly, false);
|
||||
checkAccess(undefined, testPublishOnly, false);
|
||||
checkAccess(badCredentials, testPublishOnly, false);
|
||||
checkPublish(validCredentials, testPublishOnly, true);
|
||||
checkPublish(undefined, testPublishOnly, true);
|
||||
checkPublish(badCredentials, testPublishOnly, true);
|
||||
});
|
||||
|
||||
// only user "test" is allowed to publish and access
|
||||
describe('only user "test" is allowed to publish and access', () => {
|
||||
checkAccess(validCredentials, testOnlyTest, true);
|
||||
checkAccess(undefined, testOnlyTest, false);
|
||||
checkAccess(badCredentials, testOnlyTest, false);
|
||||
checkPublish(validCredentials, testOnlyTest, true);
|
||||
checkPublish(undefined, testOnlyTest, false);
|
||||
checkPublish(badCredentials, testOnlyTest, false);
|
||||
});
|
||||
|
||||
// only authenticated users are allowed
|
||||
describe('only authenticated users are allowed', () => {
|
||||
checkAccess(validCredentials, testOnlyAuth, true);
|
||||
checkAccess(undefined, testOnlyAuth, false);
|
||||
checkAccess(badCredentials, testOnlyAuth, false);
|
||||
|
@ -91,4 +94,5 @@ export default function(server) {
|
|||
checkPublish(undefined, testOnlyAuth, false);
|
||||
checkPublish(badCredentials, testOnlyAuth, false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,27 +2,37 @@ import path from 'path';
|
|||
import _ from 'lodash';
|
||||
|
||||
import startServer from '../../../src/index';
|
||||
import {getListListenAddresses} from '../../../src/lib/bootstrap';
|
||||
import config from '../partials/config/index';
|
||||
import {DEFAULT_DOMAIN, DEFAULT_PORT} from '../../../src/lib/constants';
|
||||
import {DEFAULT_DOMAIN, DEFAULT_PORT, DEFAULT_PROTOCOL} from '../../../src/lib/constants';
|
||||
import {getListListenAddresses} from '../../../src/lib/cli/utils';
|
||||
|
||||
require('../../../src/lib/logger').setup([]);
|
||||
const logger = require('../../../src/lib/logger');
|
||||
|
||||
jest.mock('../../../src/lib/logger', () => ({
|
||||
setup: jest.fn(),
|
||||
logger: {
|
||||
child: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
error: jest.fn(),
|
||||
fatal: jest.fn()
|
||||
}
|
||||
}));
|
||||
|
||||
describe('startServer via API', () => {
|
||||
|
||||
describe('startServer launcher', () => {
|
||||
test('should provide all server data await/async', async (done) => {
|
||||
test('should provide all HTTP server data', async (done) => {
|
||||
const store = path.join(__dirname, 'partials/store');
|
||||
const serverName = 'verdaccio-test';
|
||||
const version = '1.0.0';
|
||||
const port = '6000';
|
||||
|
||||
await startServer(config, port, store, version, serverName,
|
||||
await startServer(_.clone(config), port, store, version, serverName,
|
||||
(webServer, addrs, pkgName, pkgVersion) => {
|
||||
expect(webServer).toBeDefined();
|
||||
expect(addrs).toBeDefined();
|
||||
expect(addrs.proto).toBe('http');
|
||||
expect(addrs.host).toBe('localhost');
|
||||
expect(addrs.proto).toBe(DEFAULT_PROTOCOL);
|
||||
expect(addrs.host).toBe(DEFAULT_DOMAIN);
|
||||
expect(addrs.port).toBe(port);
|
||||
expect(pkgName).toBeDefined();
|
||||
expect(pkgVersion).toBeDefined();
|
||||
|
@ -32,6 +42,28 @@ describe('startServer via API', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('should provide all HTTPS server fails', async (done) => {
|
||||
const store = path.join(__dirname, 'partials/store');
|
||||
const serverName = 'verdaccio-test';
|
||||
const version = '1.0.0';
|
||||
const address = 'https://www.domain.com:443';
|
||||
const realProcess = process;
|
||||
|
||||
const conf = _.clone(config);
|
||||
conf.https = {};
|
||||
// save process to catch exist
|
||||
const exitMock = jest.fn();
|
||||
global.process = { ...realProcess, exit: exitMock };
|
||||
await startServer(conf, address, store, version, serverName, () => {
|
||||
expect(logger.logger.fatal).toBeCalled();
|
||||
expect(logger.logger.fatal).toHaveBeenCalledTimes(2);
|
||||
done();
|
||||
});
|
||||
expect(exitMock).toHaveBeenCalledWith(2);
|
||||
// restore process
|
||||
global.process = realProcess;
|
||||
});
|
||||
|
||||
test('should fails if config is missing', async () => {
|
||||
try {
|
||||
await startServer();
|
||||
|
@ -43,27 +75,52 @@ describe('startServer via API', () => {
|
|||
});
|
||||
|
||||
describe('getListListenAddresses test', () => {
|
||||
test(`should return by default ${DEFAULT_PORT}`, () => {
|
||||
const addrs = getListListenAddresses()[0];
|
||||
|
||||
expect(addrs.proto).toBe('http');
|
||||
test('should return no address if a single address is wrong', () => {
|
||||
const addrs = getListListenAddresses("wrong");
|
||||
|
||||
expect(_.isArray(addrs)).toBeTruthy();
|
||||
expect(addrs).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('should return no address if a two address are wrong', () => {
|
||||
const addrs = getListListenAddresses(["wrong", "same-wrong"]);
|
||||
|
||||
expect(_.isArray(addrs)).toBeTruthy();
|
||||
expect(addrs).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('should return a list of 1 address provided', () => {
|
||||
const addrs = getListListenAddresses(null, '1000');
|
||||
|
||||
expect(_.isArray(addrs)).toBeTruthy();
|
||||
expect(addrs).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('should return a list of 2 address provided', () => {
|
||||
const addrs = getListListenAddresses(null, ['1000', '2000']);
|
||||
|
||||
expect(_.isArray(addrs)).toBeTruthy();
|
||||
expect(addrs).toHaveLength(2);
|
||||
});
|
||||
|
||||
test(`should return by default ${DEFAULT_PORT}`, () => {
|
||||
const [addrs] = getListListenAddresses();
|
||||
|
||||
expect(addrs.proto).toBe(DEFAULT_PROTOCOL);
|
||||
expect(addrs.host).toBe(DEFAULT_DOMAIN);
|
||||
expect(addrs.port).toBe(DEFAULT_PORT);
|
||||
});
|
||||
|
||||
test('should return a list of address and no cli argument provided', () => {
|
||||
const addrs = getListListenAddresses(null, ['1000', '2000']);
|
||||
test('should return default proto, host and custom port', () => {
|
||||
const initPort = '1000';
|
||||
const [addrs] = getListListenAddresses(null, initPort);
|
||||
|
||||
expect(_.isArray(addrs)).toBeTruthy();
|
||||
expect(addrs.proto).toEqual(DEFAULT_PROTOCOL);
|
||||
expect(addrs.host).toEqual(DEFAULT_DOMAIN);
|
||||
expect(addrs.port).toEqual(initPort);
|
||||
});
|
||||
|
||||
test('should return an address and no cli argument provided', () => {
|
||||
const addrs = getListListenAddresses(null, '1000');
|
||||
|
||||
expect(_.isArray(addrs)).toBeTruthy();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
// @flow
|
||||
|
||||
import {parseConfigurationFile} from '../__helper';
|
||||
import {parseConfigFile} from '../../../src/lib/utils';
|
||||
import {notify} from '../../../src/lib/notify';
|
||||
|
||||
import {notifyRequest} from '../../../src/lib/notify/notify-request';
|
||||
|
||||
jest.mock('./../../../src/lib/notify/notify-request', () => ({
|
||||
notifyRequest: jest.fn((options, content) => Promise.resolve([options, content]))
|
||||
}));
|
||||
|
||||
require('../../../src/lib/logger').setup([]);
|
||||
|
||||
const parseConfigurationNotifyFile = (name) => {
|
||||
return parseConfigurationFile(`notify/${name}`);
|
||||
};
|
||||
const singleNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('single.notify'));
|
||||
const singleHeaderNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('single.header.notify'));
|
||||
const packagePatternNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('single.packagePattern.notify'));
|
||||
const multiNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('multiple.notify'));
|
||||
|
||||
|
||||
describe('Notify', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
//FUTURE: we should add some sort of health check of all props, (not implemented yet)
|
||||
|
||||
test("should not fails if config is not provided", async () => {
|
||||
await notify({}, {});
|
||||
|
||||
expect(notifyRequest).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("should send notification", async () => {
|
||||
const name: string = 'package';
|
||||
const response = await notify({name}, singleNotificationConfig);
|
||||
const [options, content] = response;
|
||||
|
||||
expect(options.headers).toBeDefined();
|
||||
expect(options.url).toBeDefined();
|
||||
expect(options.body).toBeDefined();
|
||||
expect(content).toMatch(name);
|
||||
expect(response).toBeTruthy();
|
||||
expect(notifyRequest).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("should send single header notification", async () => {
|
||||
await notify({}, singleHeaderNotificationConfig);
|
||||
|
||||
expect(notifyRequest).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("should send multiple notification", async () => {
|
||||
await notify({}, multiNotificationConfig);
|
||||
|
||||
expect(notifyRequest).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
describe('packagePatternFlags', () => {
|
||||
test("should send single notification with packagePatternFlags", async () => {
|
||||
const name: string = 'package';
|
||||
await notify({name}, packagePatternNotificationConfig);
|
||||
|
||||
|
||||
expect(notifyRequest).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("should not match on send single notification with packagePatternFlags", async () => {
|
||||
const name: string = 'no-mach-name';
|
||||
await notify({name}, packagePatternNotificationConfig);
|
||||
|
||||
expect(notifyRequest).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
});
|
|
@ -4,10 +4,10 @@ import { generateGravatarUrl, GRAVATAR_DEFAULT } from '../../../src/utils/user';
|
|||
import { spliceURL } from '../../../src/utils/string';
|
||||
import Package from '../../../src/webui/components/Package/index';
|
||||
import {
|
||||
validateName as validate,
|
||||
validateName,
|
||||
convertDistRemoteToLocalTarballUrls,
|
||||
parseReadme,
|
||||
addGravatarSupport
|
||||
addGravatarSupport, validatePackage, validateMetadata, DIST_TAGS, combineBaseUrl, getVersion, normalizeDistTags
|
||||
} from '../../../src/lib/utils';
|
||||
import Logger, { setup } from '../../../src/lib/logger';
|
||||
import { readFile } from '../../functional/lib/test.utils';
|
||||
|
@ -18,6 +18,218 @@ const readmeFile = (fileName: string = 'markdown.md') =>
|
|||
setup([]);
|
||||
|
||||
describe('Utilities', () => {
|
||||
const buildURI = (host, version) =>
|
||||
`http://${host}/npm_test/-/npm_test-${version}.tgz`;
|
||||
const fakeHost = 'fake.com';
|
||||
const metadata: Package = {
|
||||
name: 'npm_test',
|
||||
versions: {
|
||||
'1.0.0': {
|
||||
dist: {
|
||||
tarball: 'http://registry.org/npm_test/-/npm_test-1.0.0.tgz'
|
||||
}
|
||||
},
|
||||
'1.0.1': {
|
||||
dist: {
|
||||
tarball: 'http://registry.org/npm_test/-/npm_test-1.0.1.tgz'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const cloneMetadata = (pkg = metadata) => Object.assign({}, pkg);
|
||||
|
||||
describe('API utilities', () => {
|
||||
describe('convertDistRemoteToLocalTarballUrls', () => {
|
||||
test('should build a URI for dist tarball based on new domain', () => {
|
||||
const convertDist = convertDistRemoteToLocalTarballUrls(cloneMetadata(),
|
||||
// $FlowFixMe
|
||||
{
|
||||
headers: {
|
||||
host: fakeHost
|
||||
},
|
||||
get: () => 'http',
|
||||
protocol: 'http'
|
||||
});
|
||||
expect(convertDist.versions['1.0.0'].dist.tarball).toEqual(buildURI(fakeHost, '1.0.0'));
|
||||
expect(convertDist.versions['1.0.1'].dist.tarball).toEqual(buildURI(fakeHost, '1.0.1'));
|
||||
});
|
||||
|
||||
test('should return same URI whether host is missing', () => {
|
||||
const convertDist = convertDistRemoteToLocalTarballUrls(cloneMetadata(),
|
||||
// $FlowFixMe
|
||||
{
|
||||
headers: {},
|
||||
get: () => 'http',
|
||||
protocol: 'http'
|
||||
});
|
||||
expect(convertDist.versions['1.0.0'].dist.tarball).toEqual(convertDist.versions['1.0.0'].dist.tarball);
|
||||
});
|
||||
});
|
||||
|
||||
describe('normalizeDistTags', () => {
|
||||
test('should delete a invalid latest version', () => {
|
||||
const pkg = cloneMetadata();
|
||||
pkg[DIST_TAGS] = {
|
||||
latest: '20000'
|
||||
};
|
||||
|
||||
normalizeDistTags(pkg)
|
||||
|
||||
expect(Object.keys(pkg[DIST_TAGS])).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('should define last published version as latest', () => {
|
||||
const pkg = cloneMetadata();
|
||||
pkg[DIST_TAGS] = {};
|
||||
|
||||
normalizeDistTags(pkg)
|
||||
|
||||
expect(pkg[DIST_TAGS]).toEqual({latest: '1.0.1'});
|
||||
});
|
||||
|
||||
test('should define last published version as latest with a custom dist-tag', () => {
|
||||
const pkg = cloneMetadata();
|
||||
pkg[DIST_TAGS] = {
|
||||
beta: '1.0.1'
|
||||
};
|
||||
|
||||
normalizeDistTags(pkg);
|
||||
|
||||
expect(pkg[DIST_TAGS]).toEqual({beta: '1.0.1', latest: '1.0.1'});
|
||||
});
|
||||
|
||||
test('should convert any array of dist-tags to a plain string', () => {
|
||||
const pkg = cloneMetadata();
|
||||
pkg[DIST_TAGS] = {
|
||||
latest: ['1.0.1']
|
||||
};
|
||||
|
||||
normalizeDistTags(pkg);
|
||||
|
||||
expect(pkg[DIST_TAGS]).toEqual({latest: '1.0.1'});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getVersion', () => {
|
||||
test('should get the right version', () => {
|
||||
expect(getVersion(cloneMetadata(), '1.0.0')).toEqual(metadata.versions['1.0.0']);
|
||||
expect(getVersion(cloneMetadata(), 'v1.0.0')).toEqual(metadata.versions['1.0.0']);
|
||||
});
|
||||
|
||||
test('should return nothing on get non existing version', () => {
|
||||
expect(getVersion(cloneMetadata(), '0')).toBeUndefined();
|
||||
expect(getVersion(cloneMetadata(), '2.0.0')).toBeUndefined();
|
||||
expect(getVersion(cloneMetadata(), 'v2.0.0')).toBeUndefined();
|
||||
expect(getVersion(cloneMetadata(), undefined)).toBeUndefined();
|
||||
expect(getVersion(cloneMetadata(), null)).toBeUndefined();
|
||||
expect(getVersion(cloneMetadata(), 2)).toBeUndefined();
|
||||
})
|
||||
});
|
||||
|
||||
describe('combineBaseUrl', () => {
|
||||
test('should create a URI', () => {
|
||||
expect(combineBaseUrl("http", 'domain')).toEqual('http://domain');
|
||||
});
|
||||
|
||||
test('should create a base url for registry', () => {
|
||||
expect(combineBaseUrl("http", 'domain', '/prefix/')).toEqual('http://domain/prefix');
|
||||
expect(combineBaseUrl("http", 'domain', 'only-prefix')).toEqual('only-prefix');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('validatePackage', () => {
|
||||
test('should validate package names', () => {
|
||||
expect(validatePackage("package-name")).toBeTruthy();
|
||||
expect(validatePackage("@scope/package-name")).toBeTruthy();
|
||||
});
|
||||
|
||||
test('should fails on validate package names', () => {
|
||||
expect(validatePackage("package-name/test/fake")).toBeFalsy();
|
||||
expect(validatePackage("@/package-name")).toBeFalsy();
|
||||
expect(validatePackage("$%$%#$%$#%#$%$#")).toBeFalsy();
|
||||
expect(validatePackage("node_modules")).toBeFalsy();
|
||||
expect(validatePackage("__proto__")).toBeFalsy();
|
||||
expect(validatePackage("package.json")).toBeFalsy();
|
||||
expect(validatePackage("favicon.ico")).toBeFalsy();
|
||||
});
|
||||
|
||||
describe('validateName', () => {
|
||||
test('should fails with no string', () => {
|
||||
// intended to fail with flow, do not remove
|
||||
// $FlowFixMe
|
||||
expect(validateName(null)).toBeFalsy();
|
||||
// $FlowFixMe
|
||||
expect(validateName()).toBeFalsy();
|
||||
});
|
||||
|
||||
test('good ones', () => {
|
||||
expect(validateName('verdaccio')).toBeTruthy();
|
||||
expect(validateName('some.weird.package-zzz')).toBeTruthy();
|
||||
expect(validateName('old-package@0.1.2.tgz')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('should be valid using uppercase', () => {
|
||||
expect(validateName('ETE')).toBeTruthy();
|
||||
expect(validateName('JSONStream')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('should fails using package.json', () => {
|
||||
expect(validateName('package.json')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('should fails with path seps', () => {
|
||||
expect(validateName('some/thing')).toBeFalsy();
|
||||
expect(validateName('some\\thing')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('should fail with no hidden files', () => {
|
||||
expect(validateName('.bin')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('should fails with reserved words', () => {
|
||||
expect(validateName('favicon.ico')).toBeFalsy();
|
||||
expect(validateName('node_modules')).toBeFalsy();
|
||||
expect(validateName('__proto__')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('should fails with other options', () => {
|
||||
expect(validateName('pk g')).toBeFalsy();
|
||||
expect(validateName('pk\tg')).toBeFalsy();
|
||||
expect(validateName('pk%20g')).toBeFalsy();
|
||||
expect(validateName('pk+g')).toBeFalsy();
|
||||
expect(validateName('pk:g')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateMetadata', () => {
|
||||
test('should fills an empty metadata object', () => {
|
||||
// intended to fail with flow, do not remove
|
||||
// $FlowFixMe
|
||||
expect(Object.keys(validateMetadata({}))).toContain(DIST_TAGS);
|
||||
// $FlowFixMe
|
||||
expect(Object.keys(validateMetadata({}))).toContain('versions');
|
||||
// $FlowFixMe
|
||||
expect(Object.keys(validateMetadata({}))).toContain('time');
|
||||
});
|
||||
|
||||
test('should fails the assertions is not an object', () => {
|
||||
expect(function ( ) {
|
||||
// $FlowFixMe
|
||||
validateMetadata('');
|
||||
}).toThrow(assert.AssertionError);
|
||||
});
|
||||
|
||||
test('should fails the assertions is name does not match', () => {
|
||||
expect(function ( ) {
|
||||
// $FlowFixMe
|
||||
validateMetadata({}, "no-name");
|
||||
}).toThrow(assert.AssertionError);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('String utilities', () => {
|
||||
test('should splice two strings and generate a url', () => {
|
||||
const url: string = spliceURL('http://domain.com', '/-/static/logo.png');
|
||||
|
@ -47,90 +259,6 @@ describe('Utilities', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Validations', () => {
|
||||
test('good ones', () => {
|
||||
assert(validate('verdaccio'));
|
||||
assert(validate('some.weird.package-zzz'));
|
||||
assert(validate('old-package@0.1.2.tgz'));
|
||||
});
|
||||
|
||||
test('uppercase', () => {
|
||||
assert(validate('EVE'));
|
||||
assert(validate('JSONStream'));
|
||||
});
|
||||
|
||||
test('no package.json', () => {
|
||||
assert(!validate('package.json'));
|
||||
});
|
||||
|
||||
test('no path seps', () => {
|
||||
assert(!validate('some/thing'));
|
||||
assert(!validate('some\\thing'));
|
||||
});
|
||||
|
||||
test('no hidden', () => {
|
||||
assert(!validate('.bin'));
|
||||
});
|
||||
|
||||
test('no reserved', () => {
|
||||
assert(!validate('favicon.ico'));
|
||||
assert(!validate('node_modules'));
|
||||
assert(!validate('__proto__'));
|
||||
});
|
||||
|
||||
test('other', () => {
|
||||
assert(!validate('pk g'));
|
||||
assert(!validate('pk\tg'));
|
||||
assert(!validate('pk%20g'));
|
||||
assert(!validate('pk+g'));
|
||||
assert(!validate('pk:g'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Packages utilities', () => {
|
||||
const metadata: Package = {
|
||||
name: 'npm_test',
|
||||
versions: {
|
||||
'1.0.0': {
|
||||
dist: {
|
||||
tarball: 'http://registry.org/npm_test/-/npm_test-1.0.0.tgz'
|
||||
}
|
||||
},
|
||||
'1.0.1': {
|
||||
dist: {
|
||||
tarball: 'http://registry.org/npm_test/-/npm_test-1.0.1.tgz'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const buildURI = (host, version) =>
|
||||
`http://${host}/npm_test/-/npm_test-${version}.tgz`;
|
||||
const host = 'fake.com';
|
||||
|
||||
test('convertDistRemoteToLocalTarballUrls', () => {
|
||||
const convertDist = convertDistRemoteToLocalTarballUrls(
|
||||
Object.assign({}, metadata),
|
||||
// $FlowFixMe
|
||||
{
|
||||
headers: {
|
||||
host
|
||||
},
|
||||
get: () => 'http',
|
||||
protocol: 'http'
|
||||
},
|
||||
''
|
||||
);
|
||||
|
||||
expect(convertDist.versions['1.0.0'].dist.tarball).toEqual(
|
||||
buildURI(host, '1.0.0')
|
||||
);
|
||||
expect(convertDist.versions['1.0.1'].dist.tarball).toEqual(
|
||||
buildURI(host, '1.0.1')
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseReadme', () => {
|
||||
test('should parse makrdown text to html template', () => {
|
||||
const markdown = '# markdown';
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
notify:
|
||||
'example-google-chat':
|
||||
method: POST
|
||||
headers: [{ 'Content-Type': 'application/json' }]
|
||||
endpoint: https://chat.googleapis.com/v1/spaces/AAAAB_TcJYs/messages?key=myKey&token=myToken
|
||||
content: '{"text":"New package published: `{{ name }}{{#each versions}} v{{version}}{{/each}}`"}'
|
||||
'example-hipchat':
|
||||
method: POST
|
||||
headers: [{ 'Content-Type': 'application/json' }]
|
||||
endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
|
||||
content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'
|
||||
'example-stride':
|
||||
method: POST
|
||||
headers:
|
||||
[
|
||||
{ 'Content-Type': 'application/json' },
|
||||
{ 'authorization': 'Bearer secretToken' },
|
||||
]
|
||||
endpoint: https://api.atlassian.com/site/{cloudId}/conversation/{conversationId}/message
|
||||
content: '{"body": {"version": 1,"type": "doc","content": [{"type": "paragraph","content": [{"type": "text","text": "New package published: * {{ name }}* Publisher name: * {{ publisher.name }}"}]}]}}'
|
|
@ -0,0 +1,5 @@
|
|||
notify:
|
||||
method: POST
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
|
||||
content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'
|
|
@ -0,0 +1,5 @@
|
|||
notify:
|
||||
method: POST
|
||||
headers: [{ 'Content-Type': 'application/json' }]
|
||||
endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
|
||||
content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'
|
|
@ -0,0 +1,7 @@
|
|||
notify:
|
||||
method: POST
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
packagePattern: package
|
||||
packagePatternFlags: g
|
||||
endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
|
||||
content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'
|
Loading…
Reference in New Issue