UNPKG

5.46 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 DBInstance from '../../shared/db';
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} from '../../shared/constant';
21import loggerInstance from '../logger';
22import {
23 getInstalledPlugins,
24 getLatestVersion,
25 getUniversalPluginVersion
26} from './utils';
27
28const pkg = require('../../../package.json');
29const { getPkgInfo } = require('../native/install');
30const version = pkg.version;
31
32const { debug, silent } = process.env;
33const root = path.join(osenv.home(), FEFLOW_ROOT);
34const configPath = path.join(root, '.feflowrc.yml');
35const universalPkgPath = path.join(root, UNIVERSAL_PKG_JSON);
36const dbFile = path.join(root, UPDATE_COLLECTION);
37const db = new DBInstance(dbFile);
38const heartDBFile = path.join(root, HEART_BEAT_COLLECTION);
39const heartDB = new DBInstance(heartDBFile);
40heartDB.setAutoCompact(BEAT_GAP * 1000);
41const logger = loggerInstance({
42 debug: Boolean(debug),
43 silent: Boolean(silent)
44});
45
46// 设置特殊的静默进程名字
47process.title = 'feflow-update-beat-proccess';
48
49const heartBeat = () => {
50 heartDB.update('beat_time', String(new Date().getTime()));
51};
52
53const queryCliUpdate = async () => {
54 const config = parseYaml(configPath);
55
56 if (!config) {
57 return;
58 }
59 if (
60 config['lastUpdateCheck'] &&
61 +new Date() - parseInt(config['lastUpdateCheck'], 10) <= 1000 * 3600 * 24
62 ) {
63 return;
64 }
65
66 if (config['autoUpdate'] !== 'true') {
67 return;
68 }
69
70 const latestVersion: any = await getLatestVersion(
71 '@feflow/cli',
72 config['packageManager']
73 );
74 if (latestVersion && semver.gt(latestVersion, version)) {
75 let updateData: any = await db.read('update_data');
76 updateData = updateData?.['value'];
77 if (updateData.latest_cli_version !== latestVersion) {
78 const newUpdateData = {
79 ...updateData,
80 latest_cli_version: latestVersion
81 };
82 await db.update('update_data', newUpdateData);
83 }
84 }
85};
86
87const queryPluginsUpdate = async () => {
88 const config = parseYaml(configPath);
89 if (!config) {
90 return;
91 }
92
93 Promise.all(
94 getInstalledPlugins().map(async (name: any) => {
95 const pluginPath = path.join(root, 'node_modules', name, 'package.json');
96 const content: any = fs.readFileSync(pluginPath);
97 const pkg: any = JSON.parse(content);
98 const localVersion = pkg.version;
99 const registryUrl = spawn
100 .sync(config['packageManager'], ['config', 'get', 'registry'], {
101 windowsHide: true
102 })
103 .stdout.toString()
104 .replace(/\n/, '')
105 .replace(/\/$/, '');
106 const latestVersion = await packageJson(name, registryUrl).catch(
107 (err: any) => {
108 logger.debug('Check plugin update error', err);
109 }
110 );
111
112 if (latestVersion && semver.gt(latestVersion, localVersion)) {
113 return {
114 name,
115 latestVersion,
116 localVersion
117 };
118 } else {
119 logger.debug('All plugins is in latest version');
120 }
121 })
122 ).then(async (plugins: any) => {
123 plugins = plugins.filter((plugin: any) => {
124 return plugin && plugin.name;
125 });
126 logger.debug('tnpm plugins update infomation', plugins);
127 if (plugins.length) {
128 let updateData: any = await db.read('update_data');
129 updateData = updateData?.['value'];
130 if (!_.isEqual(updateData.latest_plugins, plugins)) {
131 const newUpdateData = {
132 ...updateData,
133 latest_plugins: plugins
134 };
135 await db.update('update_data', newUpdateData);
136 }
137 }
138 });
139};
140
141const queryUniversalPluginsUpdate = async () => {
142 const config = parseYaml(configPath);
143 if (!config || !config['serverUrl']) {
144 return;
145 }
146 setServerUrl(config['serverUrl']);
147
148 const universalPkg = new UniversalPkg(universalPkgPath);
149 const latestUniversalPlugins: any[] = [];
150
151 // eslint-disable-next-line
152 for (const [pkg, version] of universalPkg.getInstalled()) {
153 const pkgInfo = await getPkgInfo(
154 { root, config, logger },
155 `${pkg}@${version}`
156 );
157 if (!pkgInfo) {
158 continue;
159 }
160 const versionObj = await getUniversalPluginVersion(pkgInfo, universalPkg);
161 if (versionObj.latestVersion) {
162 latestUniversalPlugins.push(versionObj);
163 }
164 }
165
166 logger.debug('universal plugins update infomation', latestUniversalPlugins);
167 if (latestUniversalPlugins.length) {
168 let updateData: any = await db.read('update_data');
169 updateData = updateData?.['value'];
170 if (
171 !_.isEqual(updateData.latest_universal_plugins, latestUniversalPlugins)
172 ) {
173 const newUpdateData = {
174 ...updateData,
175 latest_universal_plugins: latestUniversalPlugins
176 };
177 await db.update('update_data', newUpdateData);
178 }
179 }
180};
181
182// startBeat
183setInterval(heartBeat, BEAT_GAP);
184
185// queryCliUpdate
186setInterval(queryCliUpdate, CHECK_UPDATE_GAP);
187
188// queryPluginsUpdate
189setInterval(queryPluginsUpdate, CHECK_UPDATE_GAP);
190
191// queryUniversalPluginsUpdate
192setInterval(queryUniversalPluginsUpdate, CHECK_UPDATE_GAP);