flow-typed
Version:
A repository of high quality flow type definitions
193 lines (158 loc) • 7.63 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.name = exports.description = void 0;
exports.run = run;
exports.setup = setup;
var _path = _interopRequireDefault(require("path"));
var _table = require("table");
var _flowProjectUtils = require("../lib/flowProjectUtils");
var _npmLibDefs = require("../lib/npm/npmLibDefs");
var _node = require("../lib/node");
var _flowVersion = require("../lib/flowVersion");
var _codeSign = require("../lib/codeSign");
var _cacheRepoUtils = require("../lib/cacheRepoUtils");
var _ftConfig = require("../lib/ftConfig");
var _envDefs = require("../lib/envDefs");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const pullSignature = v => v.split('\n').slice(0, 2);
const name = 'outdated';
exports.name = name;
const description = 'Update the flow-typed cache and print any outdated libdefs in current project';
exports.description = description;
function setup(yargs) {
return yargs.usage(`$0 ${name}`).options({
flowVersion: {
alias: 'f',
describe: 'The Flow version that outdated libdefs must be compatible with',
type: 'string'
},
useCacheUntil: {
alias: 'u',
describe: 'Use cache until specified time in milliseconds',
type: 'number'
},
libdefDir: {
alias: 'l',
describe: 'Scan currently installed libdefs from a custom directory',
type: 'string',
demandOption: false
},
rootDir: {
alias: 'r',
describe: 'Directory of .flowconfig relative to node_modules',
type: 'string'
},
packageDir: {
alias: 'p',
describe: 'The relative path of package.json where flow-bin is installed',
type: 'string'
}
}).example('$0 outdated', '').help('h').alias('h', 'help');
}
/**
* 1. Update and pull the cache
* 2. Compare current installed with what's in the cache
* 3. Create a list to print out
*/
async function run(args) {
const cwd = typeof args.rootDir === 'string' ? _path.default.resolve(args.rootDir) : process.cwd();
const flowProjectRoot = await (0, _flowProjectUtils.findFlowRoot)(cwd);
const libdefDir = typeof args.libdefDir === 'string' ? args.libdefDir : 'flow-typed';
const packageDir = typeof args.packageDir === 'string' ? _path.default.resolve(args.packageDir) : cwd;
const flowVersion = await (0, _flowVersion.determineFlowSpecificVersion)(packageDir, args.flowVersion);
const useCacheUntil = Number(args.useCacheUntil) || _cacheRepoUtils.CACHE_REPO_EXPIRY;
if (flowProjectRoot === null) {
console.error('Error: Unable to find a flow project in the current dir or any of ' + "it's parent dirs!\n" + 'Please run this command from within a Flow project.');
return 1;
}
const cachedLibDefs = await (0, _npmLibDefs.getCacheNpmLibDefs)(useCacheUntil, true);
const installedLibDefs = await (0, _npmLibDefs.getInstalledNpmLibDefs)(flowProjectRoot, libdefDir);
let outdatedList = [];
await Promise.all(cachedLibDefs.map(async cachedDef => {
await Promise.all([...installedLibDefs.values()].map(async installedDef => {
// For each cached def we'll check if it's installed as a stub
// if so then we should mark as outdated
if (installedDef.kind === 'Stub' && installedDef.name.startsWith(`${cachedDef.name}_`)) {
const stubName = installedDef.name.substring(0, installedDef.name.indexOf('_'));
outdatedList.push({
name: stubName,
message: `A new libdef has been published to the registry replacing your stub install it with \`flow-typed install ${stubName}\``
});
}
if (installedDef.kind === 'LibDef' && installedDef.libDef.name === cachedDef.name && installedDef.libDef.scope === cachedDef.scope) {
const definitionFullName = installedDef.libDef.scope ? `${installedDef.libDef.scope}/${installedDef.libDef.name}` : installedDef.libDef.name; // If we've found a match we need to know if definition has changed
// We can just find a compatible matching library and then
// figure out if the flow signatures has changed
const npmLibDef = await (0, _npmLibDefs.findNpmLibDef)(definitionFullName, installedDef.libDef.version, flowVersion, args.useCacheUntil ? Number(args.useCacheUntil) : undefined, undefined, cachedLibDefs);
if (npmLibDef) {
const file = await _node.fs.readFile(_path.default.join(cwd, installedDef.libDef.path), 'utf-8');
const installedSignatureArray = pullSignature(file);
const repoVersion = await (0, _npmLibDefs.getNpmLibDefVersionHash)((0, _cacheRepoUtils.getCacheRepoDir)(), npmLibDef);
const codeSignPreprocessor = (0, _codeSign.signCodeStream)(repoVersion);
const content = _node.fs.readFileSync(npmLibDef.path, 'utf-8');
const cacheSignatureArray = pullSignature(codeSignPreprocessor(content));
if (installedSignatureArray[0] !== cacheSignatureArray[0] || installedSignatureArray[1] !== cacheSignatureArray[1]) {
outdatedList.push({
name: definitionFullName,
message: 'This libdef does not match what we found in the registry, update it with `flow-typed update`'
});
}
}
}
}));
}));
const ftConfig = (0, _ftConfig.getFtConfig)(cwd);
const {
env
} = ftConfig !== null && ftConfig !== void 0 ? ftConfig : {};
if (Array.isArray(env)) {
const envDefs = await (0, _envDefs.getEnvDefs)();
await Promise.all(env.map(async en => {
if (typeof en !== 'string') return;
const def = await (0, _envDefs.findEnvDef)(en, flowVersion, useCacheUntil, envDefs);
if (def) {
const localDefPath = _path.default.join(flowProjectRoot, libdefDir, 'environments', `${en}.js`);
if (!(await _node.fs.exists(localDefPath))) {
outdatedList.push({
name: en,
message: 'This env def has not yet been installed try running `flow-typed install`'
});
return;
} else {
const installedDef = _node.fs.readFileSync(localDefPath, 'utf-8');
const installedSignatureArray = pullSignature(installedDef);
const repoVersion = await (0, _envDefs.getEnvDefVersionHash)((0, _cacheRepoUtils.getCacheRepoDir)(), def);
const codeSignPreprocessor = (0, _codeSign.signCodeStream)(repoVersion);
const content = _node.fs.readFileSync(def.path, 'utf-8');
const cacheSignatureArray = pullSignature(codeSignPreprocessor(content));
if (installedSignatureArray[0] !== cacheSignatureArray[0] || installedSignatureArray[1] !== cacheSignatureArray[1]) {
outdatedList.push({
name: en,
message: 'This env definition does not match what we found in the registry, update it with `flow-typed update`'
});
}
}
} else {
outdatedList.push({
name: en,
message: 'This env definition does not exist in the registry or there is no compatible definition for your version of flow'
});
}
}));
}
if (outdatedList.length > 0) {
// Cleanup duplicated dependencies which come from nested libraries that ship flow
outdatedList = outdatedList.reduce((acc, cur) => {
if (acc.find(o => o.name === cur.name)) {
return acc;
}
return [...acc, cur];
}, []);
console.log((0, _table.table)([['Name', 'Details'], ...outdatedList.map(o => [o.name, o.message])]));
} else {
console.log('All your lib defs are up to date!');
}
return 0;
}
;