@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.
@@ -1,45 +1,61 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Updater = void 0;
4
- const tslib_1 = require("tslib");
5
- /* eslint-disable unicorn/prefer-module */
6
- const core_1 = require("@oclif/core");
7
- const chalk_1 = require("chalk");
8
- const node_fs_1 = require("node:fs");
9
- const promises_1 = require("node:fs/promises");
10
- const http_call_1 = tslib_1.__importDefault(require("http-call"));
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] = (0, filesize_1.default)(n, { output: 'array' });
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') || path.join(config.dataDir, 'client');
24
- this.clientBin = path.join(this.clientRoot, 'bin', config.windows ? `${config.bin}.cmd` : config.bin);
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, version, force = false } = options;
43
+ const { autoUpdate, force = false, version } = options;
28
44
  if (autoUpdate)
29
45
  await debounce(this.config.cacheDir);
30
- core_1.ux.action.start(`${this.config.name}: Updating CLI`);
46
+ ux.action.start(`${this.config.name}: Updating CLI`);
31
47
  if (notUpdatable(this.config)) {
32
- core_1.ux.action.stop('not updatable');
48
+ ux.action.stop('not updatable');
33
49
  return;
34
50
  }
35
51
  const [channel, current] = await Promise.all([
36
- options.channel ?? determineChannel({ version, config: this.config }),
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
- core_1.ux.action.stop(this.config.scopedEnvVar('HIDE_UPDATED_MESSAGE') ? 'done' : `already on version ${current}`);
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
- core_1.ux.action.stop();
61
- core_1.ux.log();
62
- core_1.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}.`);
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
- core_1.ux.action.stop(this.config.scopedEnvVar('HIDE_UPDATED_MESSAGE') ? 'done' : `already on version ${current}`);
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
- core_1.ux.action.stop();
91
+ ux.action.stop();
76
92
  }
77
93
  await this.touch();
78
94
  await this.tidy();
79
- core_1.ux.debug('done');
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 (0, promises_1.mkdir)(path.dirname(dst), { recursive: true });
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 (0, promises_1.writeFile)(dst, body);
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 (0, promises_1.writeFile)(dst, body, { mode: 0o755 });
205
- await (0, promises_1.rm)(path.join(this.clientRoot, 'current'), { recursive: true, force: true });
206
- await (0, promises_1.symlink)(`./${version}`, path.join(this.clientRoot, 'current'));
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 (0, promises_1.mkdir)(clientRoot, { recursive: true });
207
+ await mkdir(clientRoot, { recursive: true });
215
208
  }
216
209
  catch (error) {
217
- if (error.code === 'EEXIST') {
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 (0, promises_1.rm)(clientRoot, { recursive: true, force: true });
221
- await (0, promises_1.mkdir)(clientRoot, { recursive: true });
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
- const mtime = async (f) => (await (0, promises_1.stat)(f)).mtime;
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
- core_1.ux.warn(instructions);
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
- core_1.ux.action.status = 'fetching manifest';
240
+ ux.action.status = 'fetching manifest';
246
241
  const url = config.s3Url(s3Key);
247
- const { body } = await http_call_1.default.get(url);
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 { bin, arch } = config;
249
+ const { arch, bin } = config;
255
250
  const s3SubDir = composeS3SubDir(config);
256
- return path.join(s3SubDir, 'versions', `${bin}-${determinePlatform(config)}-${arch}-tar-gz.json`);
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 { bin, arch } = config;
255
+ const { arch, bin } = config;
261
256
  const s3SubDir = composeS3SubDir(config);
262
- return path.join(s3SubDir, 'channels', channel, `${bin}-${determinePlatform(config)}-${arch}-buildmanifest`);
257
+ return join(s3SubDir, 'channels', channel, `${bin}-${determinePlatform(config)}-${arch}-buildmanifest`);
263
258
  };
264
- const s3VersionManifestKey = ({ version, hash, config }) => {
265
- const { bin, arch } = config;
259
+ const s3VersionManifestKey = ({ config, hash, version }) => {
260
+ const { arch, bin } = config;
266
261
  const s3SubDir = composeS3SubDir(config);
267
- return path.join(s3SubDir, 'versions', version, hash, `${bin}-v${version}-${hash}-${determinePlatform(config)}-${arch}-buildmanifest`);
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 = path.join(cacheDir, 'lastrun');
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
- core_1.ux.debug(msg);
273
+ ux.debug(msg);
279
274
  }
280
275
  else {
281
- core_1.ux.log(msg);
276
+ ux.log(msg);
282
277
  output = true;
283
278
  }
284
- await (0, util_1.wait)(60 * 1000); // wait 1 minute
279
+ await wait(60 * 1000); // wait 1 minute
285
280
  return debounce(cacheDir);
286
281
  }
287
- core_1.ux.log('time to update');
282
+ ux.log('time to update');
288
283
  };
289
- const setChannel = async (channel, dataDir) => (0, promises_1.writeFile)(path.join(dataDir, 'channel'), channel, 'utf8');
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
- if (error.statusCode === 403)
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 { version, gz, sha256gz } = manifest;
303
- const gzUrl = gz ?? config.s3Url(config.s3Key('versioned', {
304
- version,
305
- channel,
306
- bin: config.bin,
307
- platform: determinePlatform(config),
308
- arch: config.arch,
309
- ext: 'gz',
310
- }));
311
- const { response: stream } = await http_call_1.default.stream(gzUrl);
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 ?? config.s3Key('baseDir', {
314
- version,
315
- channel,
316
- bin: config.bin,
317
- platform: determinePlatform(config),
318
- arch: config.arch,
319
- });
320
- const extraction = (0, tar_1.extract)(stream, baseDir, output, sha256gz);
321
- if (core_1.ux.action.type === 'spinner') {
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 = (0, lodash_throttle_1.default)((newStatus) => {
325
- core_1.ux.action.status = newStatus;
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 ({ version, config }) => {
336
- const channelPath = path.join(config.dataDir, 'channel');
337
- const channel = (0, node_fs_1.existsSync)(channelPath) ? (await (0, promises_1.readFile)(channelPath, 'utf8')).trim() : 'stable';
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 http_call_1.default.get(`${config.npmRegistry ?? 'https://registry.npmjs.org'}/${config.pjson.name}`);
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 (0, promises_1.readFile)(clientBin, 'utf8');
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
- core_1.ux.debug(error);
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
- };
@@ -1,8 +1,8 @@
1
- /// <reference types="node" />
2
- import * as fs from 'fs-extra';
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: fs.Stats;
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
+ }