@oclif/plugin-update 4.0.1-qa.0 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -10
- package/dist/commands/update.d.ts +20 -0
- package/dist/commands/update.js +83 -0
- package/dist/hooks/init.js +67 -0
- package/dist/tar.d.ts +6 -0
- package/{lib → dist}/tar.js +34 -32
- package/{lib → dist}/update.d.ts +15 -16
- package/{lib → dist}/update.js +174 -185
- package/{lib → dist}/util.d.ts +3 -3
- package/dist/util.js +22 -0
- package/oclif.lock +7082 -0
- package/oclif.manifest.json +59 -46
- package/package.json +48 -34
- package/lib/commands/update.d.ts +0 -20
- package/lib/commands/update.js +0 -87
- package/lib/hooks/init.js +0 -73
- package/lib/tar.d.ts +0 -2
- package/lib/util.js +0 -29
- /package/{lib → dist}/hooks/init.d.ts +0 -0
package/{lib → dist}/update.js
RENAMED
@@ -1,45 +1,61 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
const path = tslib_1.__importStar(require("path"));
|
12
|
-
const lodash_throttle_1 = tslib_1.__importDefault(require("lodash.throttle"));
|
13
|
-
const filesize_1 = tslib_1.__importDefault(require("filesize"));
|
14
|
-
const tar_1 = require("./tar");
|
15
|
-
const util_1 = require("./util");
|
1
|
+
import { Config, ux } from '@oclif/core';
|
2
|
+
import chalk from 'chalk';
|
3
|
+
import fileSize from 'filesize';
|
4
|
+
import { HTTP } from 'http-call';
|
5
|
+
import throttle from 'lodash.throttle';
|
6
|
+
import { existsSync } from 'node:fs';
|
7
|
+
import { mkdir, readFile, readdir, rm, stat, symlink, utimes, writeFile } from 'node:fs/promises';
|
8
|
+
import { basename, dirname, join } from 'node:path';
|
9
|
+
import { Extractor } from './tar.js';
|
10
|
+
import { ls, wait } from './util.js';
|
16
11
|
const filesize = (n) => {
|
17
|
-
const [num, suffix] = (
|
12
|
+
const [num, suffix] = fileSize(n, { output: 'array' });
|
18
13
|
return Number.parseFloat(num).toFixed(1) + ` ${suffix}`;
|
19
14
|
};
|
20
|
-
class Updater {
|
15
|
+
export class Updater {
|
16
|
+
config;
|
17
|
+
clientBin;
|
18
|
+
clientRoot;
|
21
19
|
constructor(config) {
|
22
20
|
this.config = config;
|
23
|
-
this.clientRoot = config.scopedEnvVar('OCLIF_CLIENT_HOME')
|
24
|
-
this.clientBin =
|
21
|
+
this.clientRoot = config.scopedEnvVar('OCLIF_CLIENT_HOME') ?? join(config.dataDir, 'client');
|
22
|
+
this.clientBin = join(this.clientRoot, 'bin', config.windows ? `${config.bin}.cmd` : config.bin);
|
23
|
+
}
|
24
|
+
async fetchVersionIndex() {
|
25
|
+
ux.action.status = 'fetching version index';
|
26
|
+
const newIndexUrl = this.config.s3Url(s3VersionIndexKey(this.config));
|
27
|
+
try {
|
28
|
+
const { body } = await HTTP.get(newIndexUrl);
|
29
|
+
return typeof body === 'string' ? JSON.parse(body) : body;
|
30
|
+
}
|
31
|
+
catch {
|
32
|
+
throw new Error(`No version indices exist for ${this.config.name}.`);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
async findLocalVersions() {
|
36
|
+
await ensureClientDir(this.clientRoot);
|
37
|
+
const dirOrFiles = await readdir(this.clientRoot);
|
38
|
+
return dirOrFiles
|
39
|
+
.filter((dirOrFile) => dirOrFile !== 'bin' && dirOrFile !== 'current')
|
40
|
+
.map((f) => join(this.clientRoot, f));
|
25
41
|
}
|
26
42
|
async runUpdate(options) {
|
27
|
-
const { autoUpdate,
|
43
|
+
const { autoUpdate, force = false, version } = options;
|
28
44
|
if (autoUpdate)
|
29
45
|
await debounce(this.config.cacheDir);
|
30
|
-
|
46
|
+
ux.action.start(`${this.config.name}: Updating CLI`);
|
31
47
|
if (notUpdatable(this.config)) {
|
32
|
-
|
48
|
+
ux.action.stop('not updatable');
|
33
49
|
return;
|
34
50
|
}
|
35
51
|
const [channel, current] = await Promise.all([
|
36
|
-
options.channel ?? determineChannel({
|
52
|
+
options.channel ?? determineChannel({ config: this.config, version }),
|
37
53
|
determineCurrentVersion(this.clientBin, this.config.version),
|
38
54
|
]);
|
39
55
|
if (version) {
|
40
56
|
const localVersion = force ? null : await this.findLocalVersion(version);
|
41
57
|
if (alreadyOnVersion(current, localVersion || null)) {
|
42
|
-
|
58
|
+
ux.action.stop(this.config.scopedEnvVar('HIDE_UPDATED_MESSAGE') ? 'done' : `already on version ${current}`);
|
43
59
|
return;
|
44
60
|
}
|
45
61
|
await this.config.runHook('preupdate', { channel, version });
|
@@ -57,121 +73,33 @@ class Updater {
|
|
57
73
|
await this.update(manifest, current, updated, force, channel);
|
58
74
|
}
|
59
75
|
await this.config.runHook('update', { channel, version });
|
60
|
-
|
61
|
-
|
62
|
-
|
76
|
+
ux.action.stop();
|
77
|
+
ux.log();
|
78
|
+
ux.log(`Updating to a specific version will not update the channel. If autoupdate is enabled, the CLI will eventually be updated back to ${channel}.`);
|
63
79
|
}
|
64
80
|
else {
|
65
81
|
const manifest = await fetchChannelManifest(channel, this.config);
|
66
82
|
const updated = manifest.sha ? `${manifest.version}-${manifest.sha}` : manifest.version;
|
67
83
|
if (!force && alreadyOnVersion(current, updated)) {
|
68
|
-
|
84
|
+
ux.action.stop(this.config.scopedEnvVar('HIDE_UPDATED_MESSAGE') ? 'done' : `already on version ${current}`);
|
69
85
|
}
|
70
86
|
else {
|
71
87
|
await this.config.runHook('preupdate', { channel, version: updated });
|
72
88
|
await this.update(manifest, current, updated, force, channel);
|
73
89
|
}
|
74
90
|
await this.config.runHook('update', { channel, version: updated });
|
75
|
-
|
91
|
+
ux.action.stop();
|
76
92
|
}
|
77
93
|
await this.touch();
|
78
94
|
await this.tidy();
|
79
|
-
|
80
|
-
}
|
81
|
-
async findLocalVersions() {
|
82
|
-
await ensureClientDir(this.clientRoot);
|
83
|
-
return (await (0, promises_1.readdir)(this.clientRoot))
|
84
|
-
.filter(dirOrFile => dirOrFile !== 'bin' && dirOrFile !== 'current')
|
85
|
-
.map(f => path.join(this.clientRoot, f));
|
86
|
-
}
|
87
|
-
async fetchVersionIndex() {
|
88
|
-
core_1.ux.action.status = 'fetching version index';
|
89
|
-
const newIndexUrl = this.config.s3Url(s3VersionIndexKey(this.config));
|
90
|
-
try {
|
91
|
-
const { body } = await http_call_1.default.get(newIndexUrl);
|
92
|
-
if (typeof body === 'string') {
|
93
|
-
return JSON.parse(body);
|
94
|
-
}
|
95
|
-
return body;
|
96
|
-
}
|
97
|
-
catch {
|
98
|
-
throw new Error(`No version indices exist for ${this.config.name}.`);
|
99
|
-
}
|
100
|
-
}
|
101
|
-
async fetchVersionManifest(version, url) {
|
102
|
-
const parts = url.split('/');
|
103
|
-
const hashIndex = parts.indexOf(version) + 1;
|
104
|
-
const hash = parts[hashIndex];
|
105
|
-
const s3Key = s3VersionManifestKey({ version, hash, config: this.config });
|
106
|
-
return fetchManifest(s3Key, this.config);
|
107
|
-
}
|
108
|
-
// eslint-disable-next-line max-params
|
109
|
-
async update(manifest, current, updated, force, channel) {
|
110
|
-
core_1.ux.action.start(`${this.config.name}: Updating CLI from ${(0, chalk_1.green)(current)} to ${(0, chalk_1.green)(updated)}${channel === 'stable' ? '' : ' (' + (0, chalk_1.yellow)(channel) + ')'}`);
|
111
|
-
await ensureClientDir(this.clientRoot);
|
112
|
-
const output = path.join(this.clientRoot, updated);
|
113
|
-
if (force || !(0, node_fs_1.existsSync)(output))
|
114
|
-
await downloadAndExtract(output, manifest, channel, this.config);
|
115
|
-
await this.refreshConfig(updated);
|
116
|
-
await setChannel(channel, this.config.dataDir);
|
117
|
-
await this.createBin(updated);
|
118
|
-
}
|
119
|
-
async updateToExistingVersion(current, updated) {
|
120
|
-
core_1.ux.action.start(`${this.config.name}: Updating CLI from ${(0, chalk_1.green)(current)} to ${(0, chalk_1.green)(updated)}`);
|
121
|
-
await ensureClientDir(this.clientRoot);
|
122
|
-
await this.refreshConfig(updated);
|
123
|
-
await this.createBin(updated);
|
124
|
-
}
|
125
|
-
async findLocalVersion(version) {
|
126
|
-
const versions = await this.findLocalVersions();
|
127
|
-
return versions
|
128
|
-
.map(file => path.basename(file))
|
129
|
-
.find(file => file.startsWith(version));
|
130
|
-
}
|
131
|
-
// removes any unused CLIs
|
132
|
-
async tidy() {
|
133
|
-
core_1.ux.debug('tidy');
|
134
|
-
try {
|
135
|
-
const root = this.clientRoot;
|
136
|
-
if (!(0, node_fs_1.existsSync)(root))
|
137
|
-
return;
|
138
|
-
const files = await (0, util_1.ls)(root);
|
139
|
-
const isNotSpecial = (fPath, version) => !(['bin', 'current', version].includes(path.basename(fPath)));
|
140
|
-
const isOld = (fStat) => {
|
141
|
-
const mtime = fStat.mtime;
|
142
|
-
mtime.setHours(mtime.getHours() + (42 * 24));
|
143
|
-
return mtime < new Date();
|
144
|
-
};
|
145
|
-
await Promise.all(files.filter(f => isNotSpecial(this.config.version, f.path) && isOld(f.stat))
|
146
|
-
.map(f => (0, promises_1.rm)(f.path, { recursive: true, force: true })));
|
147
|
-
await logChop(this.config.errlog);
|
148
|
-
}
|
149
|
-
catch (error) {
|
150
|
-
core_1.ux.warn(error);
|
151
|
-
}
|
152
|
-
}
|
153
|
-
async touch() {
|
154
|
-
// touch the client so it won't be tidied up right away
|
155
|
-
try {
|
156
|
-
const p = path.join(this.clientRoot, this.config.version);
|
157
|
-
core_1.ux.debug('touching client at', p);
|
158
|
-
if (!(0, node_fs_1.existsSync)(p))
|
159
|
-
return;
|
160
|
-
return (0, promises_1.utimes)(p, new Date(), new Date());
|
161
|
-
}
|
162
|
-
catch (error) {
|
163
|
-
core_1.ux.warn(error);
|
164
|
-
}
|
165
|
-
}
|
166
|
-
async refreshConfig(version) {
|
167
|
-
this.config = await core_1.Config.load({ root: path.join(this.clientRoot, version) });
|
95
|
+
ux.debug('done');
|
168
96
|
}
|
169
97
|
async createBin(version) {
|
170
98
|
const dst = this.clientBin;
|
171
99
|
const { bin, windows } = this.config;
|
172
100
|
const binPathEnvVar = this.config.scopedEnvVarKey('BINPATH');
|
173
101
|
const redirectedEnvVar = this.config.scopedEnvVarKey('REDIRECTED');
|
174
|
-
await
|
102
|
+
await mkdir(dirname(dst), { recursive: true });
|
175
103
|
if (windows) {
|
176
104
|
const body = `@echo off
|
177
105
|
setlocal enableextensions
|
@@ -179,7 +107,7 @@ set ${redirectedEnvVar}=1
|
|
179
107
|
set ${binPathEnvVar}=%~dp0${bin}
|
180
108
|
"%~dp0..\\${version}\\bin\\${bin}.cmd" %*
|
181
109
|
`;
|
182
|
-
await
|
110
|
+
await writeFile(dst, body);
|
183
111
|
}
|
184
112
|
else {
|
185
113
|
/* eslint-disable no-useless-escape */
|
@@ -201,36 +129,103 @@ DIR=$(get_script_dir)
|
|
201
129
|
${binPathEnvVar}="\$DIR/${bin}" ${redirectedEnvVar}=1 "$DIR/../${version}/bin/${bin}" "$@"
|
202
130
|
`;
|
203
131
|
/* eslint-enable no-useless-escape */
|
204
|
-
await
|
205
|
-
await
|
206
|
-
await
|
132
|
+
await writeFile(dst, body, { mode: 0o755 });
|
133
|
+
await rm(join(this.clientRoot, 'current'), { force: true, recursive: true });
|
134
|
+
await symlink(`./${version}`, join(this.clientRoot, 'current'));
|
135
|
+
}
|
136
|
+
}
|
137
|
+
async fetchVersionManifest(version, url) {
|
138
|
+
const parts = url.split('/');
|
139
|
+
const hashIndex = parts.indexOf(version) + 1;
|
140
|
+
const hash = parts[hashIndex];
|
141
|
+
const s3Key = s3VersionManifestKey({ config: this.config, hash, version });
|
142
|
+
return fetchManifest(s3Key, this.config);
|
143
|
+
}
|
144
|
+
async findLocalVersion(version) {
|
145
|
+
const versions = await this.findLocalVersions();
|
146
|
+
return versions.map((file) => basename(file)).find((file) => file.startsWith(version));
|
147
|
+
}
|
148
|
+
async refreshConfig(version) {
|
149
|
+
this.config = (await Config.load({ root: join(this.clientRoot, version) }));
|
150
|
+
}
|
151
|
+
// removes any unused CLIs
|
152
|
+
async tidy() {
|
153
|
+
ux.debug('tidy');
|
154
|
+
try {
|
155
|
+
const root = this.clientRoot;
|
156
|
+
if (!existsSync(root))
|
157
|
+
return;
|
158
|
+
const files = await ls(root);
|
159
|
+
const isNotSpecial = (fPath, version) => !['bin', 'current', version].includes(basename(fPath));
|
160
|
+
const isOld = (fStat) => {
|
161
|
+
const { mtime } = fStat;
|
162
|
+
mtime.setHours(mtime.getHours() + 42 * 24);
|
163
|
+
return mtime < new Date();
|
164
|
+
};
|
165
|
+
await Promise.all(files
|
166
|
+
.filter((f) => isNotSpecial(this.config.version, f.path) && isOld(f.stat))
|
167
|
+
.map((f) => rm(f.path, { force: true, recursive: true })));
|
168
|
+
}
|
169
|
+
catch (error) {
|
170
|
+
ux.warn(error);
|
207
171
|
}
|
208
172
|
}
|
173
|
+
async touch() {
|
174
|
+
// touch the client so it won't be tidied up right away
|
175
|
+
try {
|
176
|
+
const p = join(this.clientRoot, this.config.version);
|
177
|
+
ux.debug('touching client at', p);
|
178
|
+
if (!existsSync(p))
|
179
|
+
return;
|
180
|
+
return utimes(p, new Date(), new Date());
|
181
|
+
}
|
182
|
+
catch (error) {
|
183
|
+
ux.warn(error);
|
184
|
+
}
|
185
|
+
}
|
186
|
+
// eslint-disable-next-line max-params
|
187
|
+
async update(manifest, current, updated, force, channel) {
|
188
|
+
ux.action.start(`${this.config.name}: Updating CLI from ${chalk.green(current)} to ${chalk.green(updated)}${channel === 'stable' ? '' : ' (' + chalk.yellow(channel) + ')'}`);
|
189
|
+
await ensureClientDir(this.clientRoot);
|
190
|
+
const output = join(this.clientRoot, updated);
|
191
|
+
if (force || !existsSync(output))
|
192
|
+
await downloadAndExtract(output, manifest, channel, this.config);
|
193
|
+
await this.refreshConfig(updated);
|
194
|
+
await setChannel(channel, this.config.dataDir);
|
195
|
+
await this.createBin(updated);
|
196
|
+
}
|
197
|
+
async updateToExistingVersion(current, updated) {
|
198
|
+
ux.action.start(`${this.config.name}: Updating CLI from ${chalk.green(current)} to ${chalk.green(updated)}`);
|
199
|
+
await ensureClientDir(this.clientRoot);
|
200
|
+
await this.refreshConfig(updated);
|
201
|
+
await this.createBin(updated);
|
202
|
+
}
|
209
203
|
}
|
210
|
-
exports.Updater = Updater;
|
211
204
|
const alreadyOnVersion = (current, updated) => current === updated;
|
212
205
|
const ensureClientDir = async (clientRoot) => {
|
213
206
|
try {
|
214
|
-
await
|
207
|
+
await mkdir(clientRoot, { recursive: true });
|
215
208
|
}
|
216
209
|
catch (error) {
|
217
|
-
|
210
|
+
const { code } = error;
|
211
|
+
if (code === 'EEXIST') {
|
218
212
|
// for some reason the client directory is sometimes a file
|
219
213
|
// if so, this happens. Delete it and recreate
|
220
|
-
await
|
221
|
-
await
|
214
|
+
await rm(clientRoot, { force: true, recursive: true });
|
215
|
+
await mkdir(clientRoot, { recursive: true });
|
222
216
|
}
|
223
217
|
else {
|
224
218
|
throw error;
|
225
219
|
}
|
226
220
|
}
|
227
221
|
};
|
228
|
-
|
222
|
+
// eslint-disable-next-line unicorn/no-await-expression-member
|
223
|
+
const mtime = async (f) => (await stat(f)).mtime;
|
229
224
|
const notUpdatable = (config) => {
|
230
225
|
if (!config.binPath) {
|
231
226
|
const instructions = config.scopedEnvVar('UPDATE_INSTRUCTIONS');
|
232
227
|
if (instructions)
|
233
|
-
|
228
|
+
ux.warn(instructions);
|
234
229
|
return true;
|
235
230
|
}
|
236
231
|
return false;
|
@@ -242,89 +237,92 @@ const composeS3SubDir = (config) => {
|
|
242
237
|
return s3SubDir;
|
243
238
|
};
|
244
239
|
const fetchManifest = async (s3Key, config) => {
|
245
|
-
|
240
|
+
ux.action.status = 'fetching manifest';
|
246
241
|
const url = config.s3Url(s3Key);
|
247
|
-
const { body } = await
|
242
|
+
const { body } = await HTTP.get(url);
|
248
243
|
if (typeof body === 'string') {
|
249
244
|
return JSON.parse(body);
|
250
245
|
}
|
251
246
|
return body;
|
252
247
|
};
|
253
248
|
const s3VersionIndexKey = (config) => {
|
254
|
-
const {
|
249
|
+
const { arch, bin } = config;
|
255
250
|
const s3SubDir = composeS3SubDir(config);
|
256
|
-
return
|
251
|
+
return join(s3SubDir, 'versions', `${bin}-${determinePlatform(config)}-${arch}-tar-gz.json`);
|
257
252
|
};
|
258
253
|
const determinePlatform = (config) => config.platform === 'wsl' ? 'linux' : config.platform;
|
259
254
|
const s3ChannelManifestKey = (channel, config) => {
|
260
|
-
const {
|
255
|
+
const { arch, bin } = config;
|
261
256
|
const s3SubDir = composeS3SubDir(config);
|
262
|
-
return
|
257
|
+
return join(s3SubDir, 'channels', channel, `${bin}-${determinePlatform(config)}-${arch}-buildmanifest`);
|
263
258
|
};
|
264
|
-
const s3VersionManifestKey = ({
|
265
|
-
const {
|
259
|
+
const s3VersionManifestKey = ({ config, hash, version }) => {
|
260
|
+
const { arch, bin } = config;
|
266
261
|
const s3SubDir = composeS3SubDir(config);
|
267
|
-
return
|
262
|
+
return join(s3SubDir, 'versions', version, hash, `${bin}-v${version}-${hash}-${determinePlatform(config)}-${arch}-buildmanifest`);
|
268
263
|
};
|
269
264
|
// when autoupdating, wait until the CLI isn't active
|
270
265
|
const debounce = async (cacheDir) => {
|
271
266
|
let output = false;
|
272
|
-
const lastrunfile =
|
267
|
+
const lastrunfile = join(cacheDir, 'lastrun');
|
273
268
|
const m = await mtime(lastrunfile);
|
274
269
|
m.setHours(m.getHours() + 1);
|
275
270
|
if (m > new Date()) {
|
276
271
|
const msg = `waiting until ${m.toISOString()} to update`;
|
277
272
|
if (output) {
|
278
|
-
|
273
|
+
ux.debug(msg);
|
279
274
|
}
|
280
275
|
else {
|
281
|
-
|
276
|
+
ux.log(msg);
|
282
277
|
output = true;
|
283
278
|
}
|
284
|
-
await
|
279
|
+
await wait(60 * 1000); // wait 1 minute
|
285
280
|
return debounce(cacheDir);
|
286
281
|
}
|
287
|
-
|
282
|
+
ux.log('time to update');
|
288
283
|
};
|
289
|
-
const setChannel = async (channel, dataDir) =>
|
284
|
+
const setChannel = async (channel, dataDir) => writeFile(join(dataDir, 'channel'), channel, 'utf8');
|
290
285
|
const fetchChannelManifest = async (channel, config) => {
|
291
286
|
const s3Key = s3ChannelManifestKey(channel, config);
|
292
287
|
try {
|
293
288
|
return await fetchManifest(s3Key, config);
|
294
289
|
}
|
295
290
|
catch (error) {
|
296
|
-
|
291
|
+
const { statusCode } = error;
|
292
|
+
if (statusCode === 403)
|
297
293
|
throw new Error(`HTTP 403: Invalid channel ${channel}`);
|
298
294
|
throw error;
|
299
295
|
}
|
300
296
|
};
|
301
297
|
const downloadAndExtract = async (output, manifest, channel, config) => {
|
302
|
-
const {
|
303
|
-
const gzUrl = gz ??
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
298
|
+
const { gz, sha256gz, version } = manifest;
|
299
|
+
const gzUrl = gz ??
|
300
|
+
config.s3Url(config.s3Key('versioned', {
|
301
|
+
arch: config.arch,
|
302
|
+
bin: config.bin,
|
303
|
+
channel,
|
304
|
+
ext: 'gz',
|
305
|
+
platform: determinePlatform(config),
|
306
|
+
version,
|
307
|
+
}));
|
308
|
+
const { response: stream } = await HTTP.stream(gzUrl);
|
312
309
|
stream.pause();
|
313
|
-
const baseDir = manifest.baseDir ??
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
310
|
+
const baseDir = manifest.baseDir ??
|
311
|
+
config.s3Key('baseDir', {
|
312
|
+
arch: config.arch,
|
313
|
+
bin: config.bin,
|
314
|
+
channel,
|
315
|
+
platform: determinePlatform(config),
|
316
|
+
version,
|
317
|
+
});
|
318
|
+
const extraction = Extractor.extract(stream, baseDir, output, sha256gz);
|
319
|
+
if (ux.action.type === 'spinner') {
|
322
320
|
const total = Number.parseInt(stream.headers['content-length'], 10);
|
323
321
|
let current = 0;
|
324
|
-
const updateStatus = (
|
325
|
-
|
322
|
+
const updateStatus = throttle((newStatus) => {
|
323
|
+
ux.action.status = newStatus;
|
326
324
|
}, 250, { leading: true, trailing: false });
|
327
|
-
stream.on('data', data => {
|
325
|
+
stream.on('data', (data) => {
|
328
326
|
current += data.length;
|
329
327
|
updateStatus(`${filesize(current)}/${filesize(total)}`);
|
330
328
|
});
|
@@ -332,13 +330,14 @@ const downloadAndExtract = async (output, manifest, channel, config) => {
|
|
332
330
|
stream.resume();
|
333
331
|
await extraction;
|
334
332
|
};
|
335
|
-
const determineChannel = async ({
|
336
|
-
const channelPath =
|
337
|
-
|
333
|
+
const determineChannel = async ({ config, version }) => {
|
334
|
+
const channelPath = join(config.dataDir, 'channel');
|
335
|
+
// eslint-disable-next-line unicorn/no-await-expression-member
|
336
|
+
const channel = existsSync(channelPath) ? (await readFile(channelPath, 'utf8')).trim() : 'stable';
|
338
337
|
try {
|
339
|
-
const { body } = await
|
338
|
+
const { body } = await HTTP.get(`${config.npmRegistry ?? 'https://registry.npmjs.org'}/${config.pjson.name}`);
|
340
339
|
const tags = body['dist-tags'];
|
341
|
-
const tag = Object.keys(tags).find(v => tags[v] === version) ?? channel;
|
340
|
+
const tag = Object.keys(tags).find((v) => tags[v] === version) ?? channel;
|
342
341
|
// convert from npm style tag defaults to OCLIF style
|
343
342
|
if (tag === 'latest')
|
344
343
|
return 'stable';
|
@@ -352,22 +351,12 @@ const determineChannel = async ({ version, config }) => {
|
|
352
351
|
};
|
353
352
|
const determineCurrentVersion = async (clientBin, version) => {
|
354
353
|
try {
|
355
|
-
const currentVersion = await
|
354
|
+
const currentVersion = await readFile(clientBin, 'utf8');
|
356
355
|
const matches = currentVersion.match(/\.\.[/\\|](.+)[/\\|]bin/);
|
357
356
|
return matches ? matches[1] : version;
|
358
357
|
}
|
359
358
|
catch (error) {
|
360
|
-
|
359
|
+
ux.warn(error);
|
361
360
|
}
|
362
361
|
return version;
|
363
362
|
};
|
364
|
-
const logChop = async (errlogPath) => {
|
365
|
-
try {
|
366
|
-
core_1.ux.debug('log chop');
|
367
|
-
const logChopper = require('log-chopper').default;
|
368
|
-
await logChopper.chop(errlogPath);
|
369
|
-
}
|
370
|
-
catch (error) {
|
371
|
-
core_1.ux.debug(error.message);
|
372
|
-
}
|
373
|
-
};
|
package/{lib → dist}/util.d.ts
RENAMED
@@ -1,8 +1,8 @@
|
|
1
|
-
/// <reference types="node" />
|
2
|
-
import
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
2
|
+
import { Stats } from 'node:fs';
|
3
3
|
export declare function touch(p: string): Promise<void>;
|
4
4
|
export declare function ls(dir: string): Promise<Array<{
|
5
5
|
path: string;
|
6
|
-
stat:
|
6
|
+
stat: Stats;
|
7
7
|
}>>;
|
8
8
|
export declare function wait(ms: number, unref?: boolean): Promise<void>;
|
package/dist/util.js
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
import { readdir, stat, utimes, writeFile } from 'node:fs/promises';
|
2
|
+
import { join } from 'node:path';
|
3
|
+
export async function touch(p) {
|
4
|
+
try {
|
5
|
+
await utimes(p, new Date(), new Date());
|
6
|
+
}
|
7
|
+
catch {
|
8
|
+
await writeFile(p, '');
|
9
|
+
}
|
10
|
+
}
|
11
|
+
export async function ls(dir) {
|
12
|
+
const files = await readdir(dir);
|
13
|
+
const paths = files.map((f) => join(dir, f));
|
14
|
+
return Promise.all(paths.map((path) => stat(path).then((s) => ({ path, stat: s }))));
|
15
|
+
}
|
16
|
+
export function wait(ms, unref = false) {
|
17
|
+
return new Promise((resolve) => {
|
18
|
+
const t = setTimeout(() => resolve(), ms);
|
19
|
+
if (unref)
|
20
|
+
t.unref();
|
21
|
+
});
|
22
|
+
}
|