Skip to content

Commit

Permalink
Re-write validate-defs to use npm-specific libdef code
Browse files Browse the repository at this point in the history
This is the first step in adding support for "namespaces" to flow-typed. The
concept is pretty straightforward: Each libdef sits in a namespace, and each
namespace has its own set of rules around how libdefs are named, versioned,
tested, and installed. The current set of npm libdefs we have will go under the
"npm" namespace and this namespace will remain the default.

Namespaces will allow flow-typed to begin supporting non-npm libdefs such as the
core built-ins that are currently only embedded in Flow itself, a "staging"
namespace for less-vetted libdefs, a namespace for libdefs of atom services,
etc.
  • Loading branch information
jeffmo committed Feb 15, 2017
1 parent 1c29dfb commit 7bbd0a3
Show file tree
Hide file tree
Showing 30 changed files with 3,643 additions and 62 deletions.
3 changes: 3 additions & 0 deletions cli/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@
"presets": [
"es2015",
],
"ignore": [
"__npmLibDefs-fixtures__"
]
}
1 change: 1 addition & 0 deletions cli/.eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
dist/
flow-typed/
**/__npmLibDefs-fixtures__/**
1 change: 1 addition & 0 deletions cli/.flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ flow-typed
<PROJECT_ROOT>/.test-dir/.*
<PROJECT_ROOT>/.flow-bins-cache/.*
<PROJECT_ROOT>/node_modules/.*config-chain/test/broken.json
.*/__npmLibDefs-fixtures__/.*

[options]
experimental.const_params=true
7 changes: 5 additions & 2 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,17 @@
"name": "flow-typed-cli",
"modulePathIgnorePatterns": [
"<rootDir>/dist/.*"
],
"testPathIgnorePatterns": [
"<rootDir>/.*/__[^/]*-fixtures__/.*"
]
},
"devDependencies": {
"babel-cli": "^6.6.5",
"babel-cli": "^6.22.2",
"babel-eslint": "^6.0.4",
"babel-plugin-syntax-async-functions": "^6.5.0",
"babel-plugin-syntax-trailing-function-commas": "^6.8.0",
"babel-plugin-transform-flow-strip-types": "^6.7.0",
"babel-plugin-transform-flow-strip-types": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "6.6.5",
"babel-plugin-transform-regenerator": "^6.6.5",
"babel-preset-es2015": "^6.6.0",
Expand Down
71 changes: 36 additions & 35 deletions cli/src/commands/validateDefs.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,54 @@
// @flow

import {getLocalLibDefs as getLocalDefs} from "../lib/libDefs.js";
import isInFlowTypedRepo from "../lib/isInFlowTypedRepo";
import {
fs
} from "../lib/node";

function validationError(errKey, errMsg, validationErrs) {
const errors = validationErrs.get(errKey) || [];
errors.push(errMsg);
validationErrs.set(errKey, errors);
}
import {
getNpmLibDefs,
} from "../lib/npmLibDefs";

export const name = "validate-defs";
export const description = "Validates the structure of the definitions in the flow-typed project.";
import {
printValidationErrors,
} from "../lib/validationErrors";

export async function run(): Promise<number> {
if (!isInFlowTypedRepo()) {
console.log(
"This command only works in a clone of flowtype/flow-typed. " +
"It is a tool used to validate the library definitions flow-typed project."
export const name = "validate-defs";
export const description = "Validates the structure of the /definitions dir.";
export type Args = {
_: Array<string>,
};
export async function run(args: Args) {
if (args._.length !== 2) {
console.error(
"Please specify the path of the /definitions directory to be validated " +
"as the first arg of this command."
);
return 1;
}
const validationErrors = new Map();
const defsDirPath = args._[1];

if (!await fs.exists(defsDirPath)) {
console.error("Error: Path does not exist: %s", defsDirPath);
return 1;
}

const defsDirPathStat = await fs.stat(defsDirPath);
if (!defsDirPathStat.isDirectory()) {
console.error("Error: Path is not a directory: %s", defsDirPath);
return 1;
}

const localDefs = await getLocalDefs(validationErrors);
localDefs.forEach(def => {
if (def.testFilePaths.length === 0) {
validationError(
`${def.pkgName}_${def.pkgVersionStr}`,
'Every definition file must have at least one test file!',
validationErrors
);
}
});

console.log(" ");

validationErrors.forEach((errors, pkgNameVersion) => {
console.log("Found some problems with %s:", pkgNameVersion);
errors.forEach((err) => console.log(" • " + err));
console.log("");
});
const validationErrors = new Map();
const npmLibDefs = await getNpmLibDefs(defsDirPath, validationErrors);

if (validationErrors.size === 0) {
console.log(
`All library definitions are named and structured correctedly. ` +
`(Found ${localDefs.length})`
"All libdefs are named and structured correctly. " +
`(Found ${npmLibDefs.length})`
);
return 0;
}

printValidationErrors(validationErrors);
return 1;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
// type definitions for (some of) underscore

declare module "underscore" {
/**
* Collections
*/
declare function each<T>(o: {[key:string]: T}, iteratee: (val: T, key: string)=>void): void;
declare function each<T>(a: T[], iteratee: (val: T, key: string)=>void): void;
declare function forEach<T>(o: {[key:string]: T}, iteratee: (val: T, key: string)=>void): void;
declare function forEach<T>(a: T[], iteratee: (val: T, key: string)=>void): void;

declare function map<T, U>(a: T[], iteratee: (val: T, n: number)=>U): U[];
declare function map<K, T, U>(a: {[key:K]: T}, iteratee: (val: T, k: K)=>U): U[];
declare function collect<T, U>(a: T[], iteratee: (val: T, n: number)=>U): U[];
declare function collect<K, T, U>(a: {[key:K]: T}, iteratee: (val: T, k: K)=>U): U[];

declare function reduce<T, MemoT>(a: Array<T>, iterator: (m: MemoT, o: T)=>MemoT, initialMemo?: MemoT): MemoT;
declare function inject<T, MemoT>(a: Array<T>, iterator: (m: MemoT, o: T)=>MemoT, initialMemo?: MemoT): MemoT;
declare function foldl<T, MemoT>(a: Array<T>, iterator: (m: MemoT, o: T)=>MemoT, initialMemo?: MemoT): MemoT;

declare function reduceRight<T, MemoT>(a: Array<T>, iterator: (m: MemoT, o: T)=>MemoT, initialMemo?: MemoT): MemoT;
declare function foldr<T, MemoT>(a: Array<T>, iterator: (m: MemoT, o: T)=>MemoT, initialMemo?: MemoT): MemoT;

declare function find<T>(list: T[], predicate: (val: T)=>boolean): ?T;
declare function detect<T>(list: T[], predicate: (val: T)=>boolean): ?T;

declare function filter<T>(o: {[key:string]: T}, pred: (val: T, k: string)=>boolean): T[];
declare function filter<T>(a: T[], pred: (val: T, k: string)=>boolean): T[];
declare function select<T>(o: {[key:string]: T}, pred: (val: T, k: string)=>boolean): T[];
declare function select<T>(a: T[], pred: (val: T, k: string)=>boolean): T[];

// TODO: where

declare function findWhere<T>(list: Array<T>, properties: {[key:string]: any}): ?T;

declare function reject<T>(o: {[key:string]: T}, pred: (val: T, k: string)=>boolean): T[];
declare function reject<T>(a: T[], pred: (val: T, k: string)=>boolean): T[];

declare function every<T>(a: Array<T>, pred: (val: T)=>boolean): boolean;
declare function all<T>(a: Array<T>, pred: (val: T)=>boolean): boolean;

declare function some<T>(a: Array<T>, pred: (val: T)=>boolean): boolean;
declare function any<T>(a: Array<T>, pred: (val: T)=>boolean): boolean;

declare function contains<T>(list: T[], val: T, fromIndex?: number): boolean;
declare function includes<T>(list: T[], val: T, fromIndex?: number): boolean;

// TODO: invoke

declare function pluck(a: Array<any>, propertyName: string): Array <any>;

declare function max<T>(a: Array<T>|{[key:any]: T}): T;

declare function min<T>(a: Array<T>|{[key:any]: T}): T;

declare function sortBy<T>(a: T[], property: any): T[];
declare function sortBy<T>(a: T[], iteratee: (val: T)=>any): T[];

declare function groupBy<T>(a: Array<T>, iteratee: (val: T, index: number)=>any): {[key:string]: T[]};

// TODO: indexBy

// TODO: countBy

// TODO: shuffle

declare function sample<T>(a: T[]): T;

// TODO: toArray

declare function size(o: Object): number;
declare function size(o: Array<any>): number;

declare function partition<T>(o: {[key:string]: T}, pred: (val: T, k: string)=>boolean): [T[], T[]];
declare function partition<T>(o: Array<T>, pred: (val: T)=>boolean): [T[], T[]];

/**
* Arrays
*/
declare function first<T>(a: Array<T>, n: number): Array<T>;
declare function first<T>(a: Array<T>): T;
declare function head<T>(a: Array<T>, n: number): Array<T>;
declare function head<T>(a: Array<T>): T;
declare function take<T>(a: Array<T>, n: number): Array<T>;
declare function take<T>(a: Array<T>): T;

declare function initial<T>(a: Array<T>, n?: number): Array<T>;

declare function last<T>(a: Array<T>, n: number): Array<T>;
declare function last<T>(a: Array<T>): T;

declare function rest<T>(a: Array<T>, index?: number): Array<T>;
declare function tail<T>(a: Array<T>, index?: number): Array<T>;
declare function drop<T>(a: Array<T>, index?: number): Array<T>;

declare function compact<T>(a: Array<?T>): T[];

declare function flatten<S>(a: S[][]): S[];

declare function without<T>(a: T[], ...values: T[]): T[];

declare function union<T>(...arrays: Array<Array<T>>): Array<T>;
declare function intersection<T>(...arrays: Array<Array<T>>): Array<T>;

declare function difference<T>(array: Array<T>, ...others: Array<Array<T>>): Array<T>;

declare function uniq<T>(a: T[]): T[];
declare function unique<T>(a: T[]): T[];

declare function zip<S, T>(a1: S[], a2: T[]): Array<[S, T]>;

// TODO: unzip

declare function object<T>(a: Array<[string, T]>): {[key:string]: T};

declare function indexOf<T>(list: T[], val: T): number;

// TODO: lastIndexOf

// TODO: sortedIndex

declare function findIndex<T>(list: T[], predicate: (val: T)=>boolean): number;

// TODO: findLastIndex

declare function range(a: number, b: number): Array<number>;

/**
* Functions
*/
// TODO: bind

// TODO: bindAll

declare function partial(fn: Function, ...arguments: Array<any>): Function;

declare function memoize(fn: Function): Function;

// TODO: delay

declare function defer(fn: Function, ...arguments: Array<any>): void;

declare function throttle<T>(fn: T, wait: number, options?: {leading?: boolean, trailing?: boolean}): T;

declare function debounce<T>(fn: T, wait: number, immediate?: boolean): T;

// TODO: once

// TODO: after

// TODO: before

// TODO: wrap

// TODO: negate

declare function compose(...functions: Function[]): Function;

/**
* Objects
*/
declare function keys<K, V>(o: {[key: K]: V}): K[];

// TODO: allKeys

declare function values<K, V>(o: {[key: K]: V}): V[];

declare function mapObject<K, V>(o: {[key: K]: V}): {[key: K]: any};

declare function pairs<T>(o: {[key:string]: T}): Array<[string, T]>;

// TODO: invert

// TODO: create

// TODO: functions, methods

// TODO: findKey

declare function extend<S, T>(o1: S, o2: T): S & T;

// TODO: extendOwn, assign

declare function pick(o: any, ...keys: any): any;
declare function pick<T>(o: T, fn: (v: any, k: any, o: T) => boolean): any;

declare function omit(o: any, ...keys: Array < string > ): any;
declare function omit<T>(o: any, fn: (v: any, k: any, o: T) => boolean): any;

// TODO: defaults

declare function clone<T>(obj: T): T;

// TODO: tap

declare function has(o: any, k: any): boolean;

// TODO: matcher, matches
// TODO: property
// TODO: propertyOf

declare function isEqual(a: any, b: any): boolean;

// TODO: isMatch

declare function isEmpty(o: any): boolean;

// TODO: isElement

declare function isArray(o: any): boolean;
declare function isObject(o: any): boolean;
declare function isArguments(o: any): boolean;
declare function isFunction(o: any): boolean;
declare function isString(o: any): boolean;
declare function isNumber(o: any): boolean;
declare function isFinite(o: any): boolean;
declare function isBoolean(o: any): boolean;
declare function isDate(o: any): boolean;
declare function isRegExp(o: any): boolean;
declare function isError(o: any): boolean;
declare function isNaN(o: any): boolean;
declare function isNull(o: any): boolean;
declare function isUndefined(o: any): boolean;

/**
* Utility
*/
// TODO: noConflict
// TODO: identity
// TODO: constant
// TODO: noop
// TODO: times
// TODO: random
// TODO: mixin
// TODO: iteratee
// TODO: uniqueId
// TODO: escape
// TODO: unescape
// TODO: result
// TODO: now
declare function template(templateText: string): (values: {[key: string]: string}) => string;

/**
* Chaining
*/
declare function chain<S>(obj: S): any;
// TODO: value

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @flow */
import _ from 'underscore';

// $ExpectError
_.zip([{x:1}], [{x:2,y:1}])[0][2]
Loading

0 comments on commit 7bbd0a3

Please sign in to comment.