UNPKG

6.14 kBPlain TextView Raw
1/* eslint-disable @typescript-eslint/camelcase */
2import fs from 'fs';
3import path from 'path';
4import semver from 'semver';
5import osenv from 'osenv';
6import spawn from 'cross-spawn';
7import _ from 'lodash';
8import LockFileInstance from '../../shared/lockFile';
9import packageJson from '../../shared/packageJson';
10import { parseYaml } from '../../shared/yaml';
11import { setServerUrl } from '../../shared/git';
12import { UniversalPkg } from '../universal-pkg/dep/pkg';
13import {
14 HEART_BEAT_COLLECTION,
15 UPDATE_COLLECTION,
16 BEAT_GAP,
17 CHECK_UPDATE_GAP,
18 FEFLOW_ROOT,
19 UNIVERSAL_PKG_JSON,
20 BEAT_KEY,
21 BEAT_LOCK,
22 UPDATE_KEY,
23 UPDATE_LOCK
24} from '../../shared/constant';
25import loggerInstance from '../logger';
26import {
27 getInstalledPlugins,
28 getLatestVersion,
29 getUniversalPluginVersion
30} from './utils';
31interface ErrorInstance {
32 name: string;
33 message: string;
34 stack: string;
35}
36
37const pkg = require('../../../package.json');
38const { getPkgInfo } = require('../native/install');
39const version = pkg.version;
40
41const { debug, silent } = process.env;
42const root = path.join(osenv.home(), FEFLOW_ROOT);
43const configPath = path.join(root, '.feflowrc.yml');
44const universalPkgPath = path.join(root, UNIVERSAL_PKG_JSON);
45const dbFile = path.join(root, UPDATE_COLLECTION);
46const updateLock = path.join(root, UPDATE_LOCK);
47const updateFile = new LockFileInstance(dbFile, updateLock);
48const heartDBFile = path.join(root, HEART_BEAT_COLLECTION);
49const beatLock = path.join(root, BEAT_LOCK);
50const heartFile = new LockFileInstance(heartDBFile, beatLock);
51const logger = loggerInstance({
52 debug: Boolean(debug),
53 silent: Boolean(silent)
54});
55
56// 设置特殊的静默进程名字
57process.title = 'feflow-update-beat-proccess';
58
59const handleException = (e: ErrorInstance): void => {
60 logger.error(`update_beat_exception: ${e.name}: ${e.message} => ${e.stack}`);
61};
62
63(process as NodeJS.EventEmitter).on('uncaughtException', handleException);
64
65(process as NodeJS.EventEmitter).on('unhandledRejection', handleException);
66
67const heartBeat = () => {
68 heartFile.update(BEAT_KEY, String(new Date().getTime()));
69};
70
71const queryCliUpdate = async () => {
72 const config = parseYaml(configPath);
73
74 if (!config) {
75 return;
76 }
77 if (
78 config['lastUpdateCheck'] &&
79 +new Date() - parseInt(config['lastUpdateCheck'], 10) <= 1000 * 3600 * 24
80 ) {
81 return;
82 }
83
84 if (config['autoUpdate'] !== 'true') {
85 return;
86 }
87
88 const latestVersion: any = await getLatestVersion(
89 '@feflow/cli',
90 config['packageManager']
91 );
92 if (latestVersion && semver.gt(latestVersion, version)) {
93 const updateData: any = await updateFile.read(UPDATE_KEY);
94 if (updateData.latest_cli_version !== latestVersion) {
95 const newUpdateData = {
96 ...updateData,
97 latest_cli_version: latestVersion
98 };
99 await updateFile.update(UPDATE_KEY, newUpdateData);
100 }
101 }
102};
103
104const queryPluginsUpdate = async () => {
105 const config = parseYaml(configPath);
106 if (!config) {
107 return;
108 }
109
110 Promise.all(
111 getInstalledPlugins().map(async (name: any) => {
112 const pluginPath = path.join(root, 'node_modules', name, 'package.json');
113 const content: any = fs.readFileSync(pluginPath);
114 const pkg: any = JSON.parse(content);
115 const localVersion = pkg.version;
116 const registryUrl = spawn
117 .sync(config['packageManager'], ['config', 'get', 'registry'], {
118 windowsHide: true
119 })
120 .stdout.toString()
121 .replace(/\n/, '')
122 .replace(/\/$/, '');
123 const latestVersion = await packageJson(name, registryUrl).catch(
124 (err: any) => {
125 logger.debug('Check plugin update error', err);
126 }
127 );
128
129 if (latestVersion && semver.gt(latestVersion, localVersion)) {
130 return {
131 name,
132 latestVersion,
133 localVersion
134 };
135 } else {
136 logger.debug('All plugins is in latest version');
137 }
138 })
139 ).then(async (plugins: any) => {
140 plugins = plugins.filter((plugin: any) => {
141 return plugin && plugin.name;
142 });
143 logger.debug('tnpm plugins update infomation', plugins);
144 if (plugins.length) {
145 const updateData: any = await updateFile.read(UPDATE_KEY);
146 if (!_.isEqual(updateData.latest_plugins, plugins)) {
147 const newUpdateData = {
148 ...updateData,
149 latest_plugins: plugins
150 };
151 await updateFile.update(UPDATE_KEY, newUpdateData);
152 }
153 }
154 });
155};
156
157const queryUniversalPluginsUpdate = async () => {
158 const config = parseYaml(configPath);
159 if (!config || !config['serverUrl']) {
160 return;
161 }
162 setServerUrl(config['serverUrl']);
163
164 const universalPkg = new UniversalPkg(universalPkgPath);
165 const latestUniversalPlugins: any[] = [];
166
167 // eslint-disable-next-line
168 for (const [pkg, version] of universalPkg.getInstalled()) {
169 const pkgInfo = await getPkgInfo(
170 { root, config, logger },
171 `${pkg}@${version}`
172 ).catch(async (e: string) => {
173 logger.error(`update_error => pkg: ${pkg}@${version} => error: ${e}`);
174 });
175 if (!pkgInfo) {
176 continue;
177 }
178 const versionObj = await getUniversalPluginVersion(pkgInfo, universalPkg);
179 if (versionObj.latestVersion) {
180 latestUniversalPlugins.push(versionObj);
181 }
182 }
183
184 logger.debug('universal plugins update infomation', latestUniversalPlugins);
185 if (latestUniversalPlugins.length) {
186 const updateData: any = await updateFile.read(UPDATE_KEY);
187 if (
188 !_.isEqual(updateData.latest_universal_plugins, latestUniversalPlugins)
189 ) {
190 const newUpdateData = {
191 ...updateData,
192 latest_universal_plugins: latestUniversalPlugins
193 };
194 await updateFile.update(UPDATE_KEY, newUpdateData);
195 }
196 }
197};
198
199// startBeat
200setInterval(heartBeat, BEAT_GAP);
201
202// queryCliUpdate
203setInterval(() => {
204 queryCliUpdate().catch(handleException);
205}, CHECK_UPDATE_GAP);
206
207// queryPluginsUpdate
208setInterval(() => {
209 queryPluginsUpdate().catch(handleException);
210}, CHECK_UPDATE_GAP);
211
212// queryUniversalPluginsUpdate
213setInterval(() => {
214 queryUniversalPluginsUpdate().catch(handleException);
215}, CHECK_UPDATE_GAP);