UNPKG

7.63 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.name = exports.description = void 0;
7exports.run = run;
8exports.setup = setup;
9
10var _path = _interopRequireDefault(require("path"));
11
12var _table = require("table");
13
14var _flowProjectUtils = require("../lib/flowProjectUtils");
15
16var _npmLibDefs = require("../lib/npm/npmLibDefs");
17
18var _node = require("../lib/node");
19
20var _flowVersion = require("../lib/flowVersion");
21
22var _codeSign = require("../lib/codeSign");
23
24var _cacheRepoUtils = require("../lib/cacheRepoUtils");
25
26var _ftConfig = require("../lib/ftConfig");
27
28var _envDefs = require("../lib/envDefs");
29
30function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
32const pullSignature = v => v.split('\n').slice(0, 2);
33
34const name = 'outdated';
35exports.name = name;
36const description = 'Update the flow-typed cache and print any outdated libdefs in current project';
37exports.description = description;
38
39function setup(yargs) {
40 return yargs.usage(`$0 ${name}`).options({
41 flowVersion: {
42 alias: 'f',
43 describe: 'The Flow version that outdated libdefs must be compatible with',
44 type: 'string'
45 },
46 useCacheUntil: {
47 alias: 'u',
48 describe: 'Use cache until specified time in milliseconds',
49 type: 'number'
50 },
51 libdefDir: {
52 alias: 'l',
53 describe: 'Scan currently installed libdefs from a custom directory',
54 type: 'string',
55 demandOption: false
56 },
57 rootDir: {
58 alias: 'r',
59 describe: 'Directory of .flowconfig relative to node_modules',
60 type: 'string'
61 },
62 packageDir: {
63 alias: 'p',
64 describe: 'The relative path of package.json where flow-bin is installed',
65 type: 'string'
66 }
67 }).example('$0 outdated', '').help('h').alias('h', 'help');
68}
69
70/**
71 * 1. Update and pull the cache
72 * 2. Compare current installed with what's in the cache
73 * 3. Create a list to print out
74 */
75async function run(args) {
76 const cwd = typeof args.rootDir === 'string' ? _path.default.resolve(args.rootDir) : process.cwd();
77 const flowProjectRoot = await (0, _flowProjectUtils.findFlowRoot)(cwd);
78 const libdefDir = typeof args.libdefDir === 'string' ? args.libdefDir : 'flow-typed';
79 const packageDir = typeof args.packageDir === 'string' ? _path.default.resolve(args.packageDir) : cwd;
80 const flowVersion = await (0, _flowVersion.determineFlowSpecificVersion)(packageDir, args.flowVersion);
81
82 const useCacheUntil = Number(args.useCacheUntil) || _cacheRepoUtils.CACHE_REPO_EXPIRY;
83
84 if (flowProjectRoot === null) {
85 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.');
86 return 1;
87 }
88
89 const cachedLibDefs = await (0, _npmLibDefs.getCacheNpmLibDefs)(useCacheUntil, true);
90 const installedLibDefs = await (0, _npmLibDefs.getInstalledNpmLibDefs)(flowProjectRoot, libdefDir);
91 let outdatedList = [];
92 await Promise.all(cachedLibDefs.map(async cachedDef => {
93 await Promise.all([...installedLibDefs.values()].map(async installedDef => {
94 // For each cached def we'll check if it's installed as a stub
95 // if so then we should mark as outdated
96 if (installedDef.kind === 'Stub' && installedDef.name.startsWith(`${cachedDef.name}_`)) {
97 const stubName = installedDef.name.substring(0, installedDef.name.indexOf('_'));
98 outdatedList.push({
99 name: stubName,
100 message: `A new libdef has been published to the registry replacing your stub install it with \`flow-typed install ${stubName}\``
101 });
102 }
103
104 if (installedDef.kind === 'LibDef' && installedDef.libDef.name === cachedDef.name && installedDef.libDef.scope === cachedDef.scope) {
105 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
106 // We can just find a compatible matching library and then
107 // figure out if the flow signatures has changed
108
109 const npmLibDef = await (0, _npmLibDefs.findNpmLibDef)(definitionFullName, installedDef.libDef.version, flowVersion, args.useCacheUntil ? Number(args.useCacheUntil) : undefined, undefined, cachedLibDefs);
110
111 if (npmLibDef) {
112 const file = await _node.fs.readFile(_path.default.join(cwd, installedDef.libDef.path), 'utf-8');
113 const installedSignatureArray = pullSignature(file);
114 const repoVersion = await (0, _npmLibDefs.getNpmLibDefVersionHash)((0, _cacheRepoUtils.getCacheRepoDir)(), npmLibDef);
115 const codeSignPreprocessor = (0, _codeSign.signCodeStream)(repoVersion);
116
117 const content = _node.fs.readFileSync(npmLibDef.path, 'utf-8');
118
119 const cacheSignatureArray = pullSignature(codeSignPreprocessor(content));
120
121 if (installedSignatureArray[0] !== cacheSignatureArray[0] || installedSignatureArray[1] !== cacheSignatureArray[1]) {
122 outdatedList.push({
123 name: definitionFullName,
124 message: 'This libdef does not match what we found in the registry, update it with `flow-typed update`'
125 });
126 }
127 }
128 }
129 }));
130 }));
131 const ftConfig = (0, _ftConfig.getFtConfig)(cwd);
132 const {
133 env
134 } = ftConfig !== null && ftConfig !== void 0 ? ftConfig : {};
135
136 if (Array.isArray(env)) {
137 const envDefs = await (0, _envDefs.getEnvDefs)();
138 await Promise.all(env.map(async en => {
139 if (typeof en !== 'string') return;
140 const def = await (0, _envDefs.findEnvDef)(en, flowVersion, useCacheUntil, envDefs);
141
142 if (def) {
143 const localDefPath = _path.default.join(flowProjectRoot, libdefDir, 'environments', `${en}.js`);
144
145 if (!(await _node.fs.exists(localDefPath))) {
146 outdatedList.push({
147 name: en,
148 message: 'This env def has not yet been installed try running `flow-typed install`'
149 });
150 return;
151 } else {
152 const installedDef = _node.fs.readFileSync(localDefPath, 'utf-8');
153
154 const installedSignatureArray = pullSignature(installedDef);
155 const repoVersion = await (0, _envDefs.getEnvDefVersionHash)((0, _cacheRepoUtils.getCacheRepoDir)(), def);
156 const codeSignPreprocessor = (0, _codeSign.signCodeStream)(repoVersion);
157
158 const content = _node.fs.readFileSync(def.path, 'utf-8');
159
160 const cacheSignatureArray = pullSignature(codeSignPreprocessor(content));
161
162 if (installedSignatureArray[0] !== cacheSignatureArray[0] || installedSignatureArray[1] !== cacheSignatureArray[1]) {
163 outdatedList.push({
164 name: en,
165 message: 'This env definition does not match what we found in the registry, update it with `flow-typed update`'
166 });
167 }
168 }
169 } else {
170 outdatedList.push({
171 name: en,
172 message: 'This env definition does not exist in the registry or there is no compatible definition for your version of flow'
173 });
174 }
175 }));
176 }
177
178 if (outdatedList.length > 0) {
179 // Cleanup duplicated dependencies which come from nested libraries that ship flow
180 outdatedList = outdatedList.reduce((acc, cur) => {
181 if (acc.find(o => o.name === cur.name)) {
182 return acc;
183 }
184
185 return [...acc, cur];
186 }, []);
187 console.log((0, _table.table)([['Name', 'Details'], ...outdatedList.map(o => [o.name, o.message])]));
188 } else {
189 console.log('All your lib defs are up to date!');
190 }
191
192 return 0;
193}
\No newline at end of file