1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.name = exports.description = void 0;
|
7 | exports.run = run;
|
8 | exports.setup = setup;
|
9 |
|
10 | var _path = _interopRequireDefault(require("path"));
|
11 |
|
12 | var _table = require("table");
|
13 |
|
14 | var _flowProjectUtils = require("../lib/flowProjectUtils");
|
15 |
|
16 | var _npmLibDefs = require("../lib/npm/npmLibDefs");
|
17 |
|
18 | var _node = require("../lib/node");
|
19 |
|
20 | var _flowVersion = require("../lib/flowVersion");
|
21 |
|
22 | var _codeSign = require("../lib/codeSign");
|
23 |
|
24 | var _cacheRepoUtils = require("../lib/cacheRepoUtils");
|
25 |
|
26 | var _ftConfig = require("../lib/ftConfig");
|
27 |
|
28 | var _envDefs = require("../lib/envDefs");
|
29 |
|
30 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
31 |
|
32 | const pullSignature = v => v.split('\n').slice(0, 2);
|
33 |
|
34 | const name = 'outdated';
|
35 | exports.name = name;
|
36 | const description = 'Update the flow-typed cache and print any outdated libdefs in current project';
|
37 | exports.description = description;
|
38 |
|
39 | function 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 |
|
72 |
|
73 |
|
74 |
|
75 | async 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 |
|
95 |
|
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;
|
106 |
|
107 |
|
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 |
|
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 |