@oclif/plugin-update 4.0.1-qa.0 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }