@mikeyt23/node-cli-utils 2.0.0-beta.1 → 2.0.0-beta.3
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/dist/cjs/DependencyChecker.d.ts +26 -0
- package/dist/cjs/DependencyChecker.d.ts.map +1 -0
- package/dist/cjs/DependencyChecker.js +200 -0
- package/dist/cjs/GitUtility.d.ts +7 -0
- package/dist/cjs/GitUtility.d.ts.map +1 -0
- package/dist/cjs/GitUtility.js +49 -0
- package/dist/cjs/NixUtil.d.ts +8 -0
- package/dist/cjs/NixUtil.d.ts.map +1 -0
- package/dist/cjs/NixUtil.js +50 -0
- package/dist/cjs/TarballUtility.d.ts +17 -7
- package/dist/cjs/TarballUtility.d.ts.map +1 -1
- package/dist/cjs/TarballUtility.js +18 -24
- package/dist/cjs/certUtils.d.ts +53 -17
- package/dist/cjs/certUtils.d.ts.map +1 -1
- package/dist/cjs/certUtils.js +176 -111
- package/dist/cjs/colors.d.ts +17 -0
- package/dist/cjs/colors.d.ts.map +1 -0
- package/dist/cjs/colors.js +30 -0
- package/dist/cjs/dbMigrationUtils.js +44 -54
- package/dist/cjs/dotnetUtils.d.ts.map +1 -1
- package/dist/cjs/dotnetUtils.js +4 -2
- package/dist/cjs/esmSpecific.d.mts +5 -0
- package/dist/cjs/esmSpecific.d.mts.map +1 -1
- package/dist/cjs/esmSpecific.mjs +6 -1
- package/dist/cjs/generalUtils.d.ts +252 -26
- package/dist/cjs/generalUtils.d.ts.map +1 -1
- package/dist/cjs/generalUtils.js +503 -107
- package/dist/cjs/generalUtilsInternal.d.ts +9 -3
- package/dist/cjs/generalUtilsInternal.d.ts.map +1 -1
- package/dist/cjs/generalUtilsInternal.js +160 -59
- package/dist/cjs/hostFileUtils.d.ts +18 -0
- package/dist/cjs/hostFileUtils.d.ts.map +1 -0
- package/dist/cjs/hostFileUtils.js +100 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/runWhileParentAlive.js +7 -9
- package/dist/cjs/testUtils.d.ts +11 -0
- package/dist/cjs/testUtils.d.ts.map +1 -0
- package/dist/cjs/testUtils.js +58 -0
- package/dist/esm/DependencyChecker.d.ts +26 -0
- package/dist/esm/DependencyChecker.d.ts.map +1 -0
- package/dist/esm/DependencyChecker.js +172 -0
- package/dist/esm/GitUtility.d.ts +7 -0
- package/dist/esm/GitUtility.d.ts.map +1 -0
- package/dist/esm/GitUtility.js +43 -0
- package/dist/esm/NixUtil.d.ts +8 -0
- package/dist/esm/NixUtil.d.ts.map +1 -0
- package/dist/esm/NixUtil.js +46 -0
- package/dist/esm/TarballUtility.d.ts +17 -7
- package/dist/esm/TarballUtility.d.ts.map +1 -1
- package/dist/esm/TarballUtility.js +21 -25
- package/dist/esm/certUtils.d.ts +53 -17
- package/dist/esm/certUtils.d.ts.map +1 -1
- package/dist/esm/certUtils.js +173 -86
- package/dist/esm/colors.d.ts +17 -0
- package/dist/esm/colors.d.ts.map +1 -0
- package/dist/esm/colors.js +20 -0
- package/dist/esm/dbMigrationUtils.js +45 -55
- package/dist/esm/dotnetUtils.d.ts.map +1 -1
- package/dist/esm/dotnetUtils.js +4 -2
- package/dist/esm/esmSpecific.d.mts +5 -0
- package/dist/esm/esmSpecific.d.mts.map +1 -1
- package/dist/esm/esmSpecific.mjs +6 -1
- package/dist/esm/generalUtils.d.ts +252 -26
- package/dist/esm/generalUtils.d.ts.map +1 -1
- package/dist/esm/generalUtils.js +477 -105
- package/dist/esm/generalUtilsInternal.d.ts +9 -3
- package/dist/esm/generalUtilsInternal.d.ts.map +1 -1
- package/dist/esm/generalUtilsInternal.js +151 -57
- package/dist/esm/hostFileUtils.d.ts +18 -0
- package/dist/esm/hostFileUtils.d.ts.map +1 -0
- package/dist/esm/hostFileUtils.js +85 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/runWhileParentAlive.js +8 -10
- package/dist/esm/testUtils.d.ts +11 -0
- package/dist/esm/testUtils.d.ts.map +1 -0
- package/dist/esm/testUtils.js +47 -0
- package/package.json +38 -2
package/dist/esm/generalUtils.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { exec, spawnSync } from 'node:child_process';
|
|
2
1
|
import fs from 'node:fs';
|
|
3
2
|
import fsp from 'node:fs/promises';
|
|
4
3
|
import { platform } from 'node:os';
|
|
5
4
|
import path, { resolve } from 'node:path';
|
|
6
5
|
import * as readline from 'readline';
|
|
6
|
+
import * as net from 'net';
|
|
7
7
|
import { config } from './NodeCliUtilsConfig.js';
|
|
8
|
-
import { copyEnv, dictionaryToEnvFileString, getEnvAsDictionary, spawnAsyncInternal } from './generalUtilsInternal.js';
|
|
8
|
+
import { copyEnv, dictionaryToEnvFileString, getEnvAsDictionary, simpleSpawnAsyncInternal, simpleSpawnSyncInternal, spawnAsyncInternal, validateFindFilesRecursivelyParams, whichInternal } from './generalUtilsInternal.js';
|
|
9
9
|
const dockerComposeCommandsThatSupportDetached = ['exec', 'logs', 'ps', 'restart', 'run', 'start', 'stop', 'up'];
|
|
10
10
|
/**
|
|
11
11
|
* Just a wrapper for console.log() to type less.
|
|
@@ -15,6 +15,16 @@ const dockerComposeCommandsThatSupportDetached = ['exec', 'logs', 'ps', 'restart
|
|
|
15
15
|
export function log(data, ...moreData) {
|
|
16
16
|
console.log(data, ...moreData);
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Log conditionally. Useful for methods that have an option to either suppress output or to show it when it normally isn't.
|
|
20
|
+
* @param data The data to log
|
|
21
|
+
* @param moreData More data to log
|
|
22
|
+
*/
|
|
23
|
+
export function logIf(shouldLog, data, ...moreData) {
|
|
24
|
+
if (shouldLog) {
|
|
25
|
+
console.log(data, ...moreData);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
18
28
|
/**
|
|
19
29
|
* Wrapper for console.log() that is suppressed if NodeCliUtilsConfig.logEnabled is false.
|
|
20
30
|
* @param data The data to log
|
|
@@ -61,46 +71,67 @@ export async function sleep(ms) {
|
|
|
61
71
|
});
|
|
62
72
|
}
|
|
63
73
|
/**
|
|
64
|
-
* This is a wrapper function for NodeJS. Defaults stdio to inherit so that output is visible in the console,
|
|
65
|
-
* but note that this means stdout and stderr will not be available in the returned SpawnResult.
|
|
74
|
+
* This is a wrapper function for NodeJS spawn. Defaults stdio to inherit so that output is visible in the console,
|
|
75
|
+
* but note that this means stdout and stderr will not be available in the returned SpawnResult. To hide the output
|
|
76
|
+
* from the console but collect the stdout and stderr in the SpawnResult, use stdio: 'pipe'.
|
|
66
77
|
*
|
|
67
78
|
* When spawning long-running processes, use {@link spawnAsyncLongRunning} instead so that unexpected
|
|
68
79
|
* termination of the parent process will not orphan the child process tree on windows.
|
|
80
|
+
*
|
|
81
|
+
* **Warning:** Do NOT use this for generating commands dynamically from user input as it could be used to execute arbitrary code.
|
|
82
|
+
* This is meant solely for building up known commands that are not made up of unsanitized user input, and only at compile time.
|
|
83
|
+
* See {@link winInstallCert} and {@link winUninstallCert} for examples of taking user input and inserting it safely into known commands.
|
|
69
84
|
* @param command The command to spawn
|
|
70
85
|
* @param args The arguments to pass to the command
|
|
71
86
|
* @param options The options to pass to the command
|
|
72
87
|
* @returns A Promise that resolves to a {@link SpawnResult}
|
|
73
88
|
*/
|
|
74
89
|
export async function spawnAsync(command, args, options) {
|
|
75
|
-
return spawnAsyncInternal(command, args, options);
|
|
90
|
+
return spawnAsyncInternal(command, args ?? [], options);
|
|
76
91
|
}
|
|
77
92
|
/**
|
|
78
93
|
* Use this alternate spawn wrapper instead of {@link spawnAsync} when spawning long-running processes to
|
|
79
94
|
* avoid orphaned child process trees on Windows.
|
|
95
|
+
*
|
|
96
|
+
* **Warning:** Do NOT use this for generating commands dynamically from user input as it could be used to execute arbitrary code.
|
|
97
|
+
* This is meant solely for building up known commands that are not made up of unsanitized user input, and only at compile time.
|
|
98
|
+
* See {@link winInstallCert} and {@link winUninstallCert} for examples of taking user input and inserting it safely into known commands.
|
|
80
99
|
* @param command The command to spawn
|
|
81
100
|
* @param args The arguments to pass to the command
|
|
82
101
|
* @param cwd The current working directory to run the command from - defaults to process.cwd()
|
|
83
102
|
* @returns A Promise that resolves to a {@link SpawnResult}
|
|
84
103
|
*/
|
|
85
104
|
export async function spawnAsyncLongRunning(command, args, cwd) {
|
|
86
|
-
return spawnAsyncInternal(command, args, { cwd: cwd, isLongRunning: true });
|
|
105
|
+
return spawnAsyncInternal(command, args ?? [], { cwd: cwd, isLongRunning: true });
|
|
87
106
|
}
|
|
88
107
|
/**
|
|
89
108
|
* Ensure the directory exists. Similar to `mkdir -p` (creates parent directories if they don't exist).
|
|
90
109
|
* @param dir The directory to ensure exists. If it does not exist, it will be created.
|
|
91
110
|
*/
|
|
92
111
|
export async function ensureDirectory(dir) {
|
|
112
|
+
return await mkdirp(dir);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Create a directory. Will create parent directory structure if it don't exist. Similar to `mkdir -p`.
|
|
116
|
+
* @param dir The directory to create.
|
|
117
|
+
*/
|
|
118
|
+
export async function mkdirp(dir) {
|
|
93
119
|
requireString('dir', dir);
|
|
94
|
-
|
|
95
|
-
await
|
|
120
|
+
try {
|
|
121
|
+
await fsp.mkdir(dir, { recursive: true });
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
// Must catch and re-throw in order to get a stack trace: https://github.com/nodejs/node/issues/30944
|
|
125
|
+
throw new ExtendedError('Error creating directory', getNormalizedError(err));
|
|
96
126
|
}
|
|
97
127
|
}
|
|
98
128
|
/**
|
|
99
129
|
* Create a directory. Will create parent directory structure if it don't exist. Similar to `mkdir -p`.
|
|
100
130
|
* @param dir The directory to create.
|
|
101
131
|
*/
|
|
102
|
-
export async function
|
|
103
|
-
|
|
132
|
+
export async function mkdirpSync(dir) {
|
|
133
|
+
requireString('dir', dir);
|
|
134
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
104
135
|
}
|
|
105
136
|
/**
|
|
106
137
|
* Empties a directory of all files and subdirectories.
|
|
@@ -134,7 +165,7 @@ export async function emptyDirectory(directoryToEmpty, fileAndDirectoryNamesToSk
|
|
|
134
165
|
}
|
|
135
166
|
let dirEntry = await dir.read();
|
|
136
167
|
while (dirEntry) {
|
|
137
|
-
if (fileAndDirectoryNamesToSkip
|
|
168
|
+
if (fileAndDirectoryNamesToSkip?.includes(dirEntry.name)) {
|
|
138
169
|
dirEntry = await dir.read();
|
|
139
170
|
continue;
|
|
140
171
|
}
|
|
@@ -186,19 +217,14 @@ export async function copyDirectoryContents(sourceDirectory, destinationDirector
|
|
|
186
217
|
}
|
|
187
218
|
}
|
|
188
219
|
/**
|
|
189
|
-
* Helper method to validate that a non-falsy value is provided for a parameter that should be a string.
|
|
190
|
-
*
|
|
191
|
-
* **Warning:** this does not validate the type of the parameter, just whether something non-empty was provided.
|
|
192
|
-
* @param paramName The name of the parameter, for logging purposes
|
|
220
|
+
* Helper method to validate that a non-falsy and non-empty value is provided for a parameter that should be a string.
|
|
221
|
+
* @param paramName The name of the parameter to be used in the error message
|
|
193
222
|
* @param paramValue The value of the parameter
|
|
194
223
|
*/
|
|
195
224
|
export function requireString(paramName, paramValue) {
|
|
196
|
-
if (paramValue === undefined || paramValue === null || paramValue === '') {
|
|
225
|
+
if (paramValue === undefined || paramValue === null || paramValue === '' || typeof paramValue !== 'string' || paramValue.trim() === '') {
|
|
197
226
|
throw new Error(`Required param '${paramName}' is missing`);
|
|
198
227
|
}
|
|
199
|
-
if (typeof paramValue !== 'string') {
|
|
200
|
-
throw new Error(`Required param '${paramName}' is not a string`);
|
|
201
|
-
}
|
|
202
228
|
}
|
|
203
229
|
/**
|
|
204
230
|
* Helper method to validate that the path actually exists for the provided value.
|
|
@@ -212,7 +238,28 @@ export function requireValidPath(paramName, paramValue) {
|
|
|
212
238
|
}
|
|
213
239
|
}
|
|
214
240
|
/**
|
|
215
|
-
*
|
|
241
|
+
* Project names must contain only lowercase letters, decimal digits, dashes, and underscores, and must begin with a lowercase letter or decimal digit.
|
|
242
|
+
*
|
|
243
|
+
* See https://docs.docker.com/compose/environment-variables/envvars/#compose_project_name.
|
|
244
|
+
* @param projectName The string to validate
|
|
245
|
+
* @returns `true` if it's a valid docker compose project name and `false` otherwise
|
|
246
|
+
*/
|
|
247
|
+
export function isDockerComposeProjectNameValid(projectName) {
|
|
248
|
+
requireString('projectName', projectName);
|
|
249
|
+
// Ensure first char is a lowercase letter or digit
|
|
250
|
+
if (!/^[a-z0-9]/.test(projectName[0])) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
// Ensure the rest of the chars are only lowercase letters, digits, dashes and underscores
|
|
254
|
+
return /^[a-z0-9-_]+$/.test(projectName);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* For docker compose commands, see https://docs.docker.com/compose/reference/. For available options for this wrapper function, see {@link DockerComposeOptions}.
|
|
258
|
+
*
|
|
259
|
+
* The current working directory will be the directory of the {@link dockerComposePath} unless specified in the options. This ensures relative paths in the
|
|
260
|
+
* docker compose file will be relative to itself by default.
|
|
261
|
+
*
|
|
262
|
+
* See {@link DockerComposeOptions.projectName} for info on where to locate your docker compose file and how to specify the docker project name.
|
|
216
263
|
* @param dockerComposePath Path to docker-compose.yml
|
|
217
264
|
* @param dockerComposeCommand The docker-compose command to run
|
|
218
265
|
* @param options {@link DockerComposeOptions} to use, including additional arguments to pass to the docker compose command and the project name
|
|
@@ -220,44 +267,54 @@ export function requireValidPath(paramName, paramValue) {
|
|
|
220
267
|
export async function spawnDockerCompose(dockerComposePath, dockerComposeCommand, options) {
|
|
221
268
|
requireValidPath('dockerComposePath', dockerComposePath);
|
|
222
269
|
requireString('dockerComposeCommand', dockerComposeCommand);
|
|
223
|
-
|
|
224
|
-
|
|
270
|
+
if (options?.cwd) {
|
|
271
|
+
requireValidPath('cwd', options.cwd);
|
|
272
|
+
}
|
|
273
|
+
if (options?.projectName && !isDockerComposeProjectNameValid(options.projectName)) {
|
|
274
|
+
throw new Error('Invalid docker compose project name specified for the projectName param. Project names must contain only lowercase letters, decimal digits, dashes, and underscores, and must begin with a lowercase letter or decimal digit.');
|
|
275
|
+
}
|
|
276
|
+
if (options?.profile && !/[a-zA-Z0-9][a-zA-Z0-9_.-]+/.test(options.profile)) {
|
|
277
|
+
throw new Error('Invalid profile option - must match regex: [a-zA-Z0-9][a-zA-Z0-9_.-]+');
|
|
278
|
+
}
|
|
279
|
+
if (!await isDockerRunning()) {
|
|
225
280
|
throw new Error('Docker is not running');
|
|
226
281
|
}
|
|
227
|
-
const defaultOptions = { attached: false };
|
|
282
|
+
const defaultOptions = { args: [], attached: false, projectName: undefined, cwd: undefined };
|
|
228
283
|
const mergedOptions = { ...defaultOptions, ...options };
|
|
229
284
|
const dockerComposeDir = path.dirname(dockerComposePath);
|
|
230
285
|
const dockerComposeFilename = path.basename(dockerComposePath);
|
|
231
|
-
|
|
232
|
-
|
|
286
|
+
if (!mergedOptions.cwd) {
|
|
287
|
+
mergedOptions.cwd = dockerComposeDir;
|
|
288
|
+
}
|
|
289
|
+
let spawnArgs = ['compose', '-f', mergedOptions.cwd ? path.resolve(dockerComposePath) : dockerComposeFilename];
|
|
233
290
|
if (mergedOptions.projectName) {
|
|
234
291
|
spawnArgs.push('--project-name', mergedOptions.projectName);
|
|
235
292
|
}
|
|
293
|
+
if (mergedOptions.profile) {
|
|
294
|
+
spawnArgs.push('--profile', mergedOptions.profile);
|
|
295
|
+
}
|
|
236
296
|
spawnArgs.push(dockerComposeCommand);
|
|
237
297
|
if (!mergedOptions.attached && dockerComposeCommandsThatSupportDetached.includes(dockerComposeCommand)) {
|
|
238
|
-
spawnArgs.push('
|
|
298
|
+
spawnArgs.push('--detach');
|
|
239
299
|
}
|
|
240
300
|
if (mergedOptions.args) {
|
|
241
301
|
spawnArgs = spawnArgs.concat(mergedOptions.args);
|
|
242
302
|
}
|
|
243
|
-
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
`running command: ${dockerCommandString}`;
|
|
247
|
-
trace(traceMessage);
|
|
248
|
-
const longRunning = dockerComposeCommandsThatSupportDetached.includes(dockerComposeCommand) && options && options.attached;
|
|
303
|
+
trace(`running command in ${mergedOptions.cwd}: docker ${spawnArgs.join(' ')}`);
|
|
304
|
+
const longRunning = dockerComposeCommandsThatSupportDetached.includes(dockerComposeCommand) && options?.attached === true;
|
|
305
|
+
trace(`docker compose command will be configured to use long running options: ${longRunning}`);
|
|
249
306
|
const spawnOptions = {
|
|
250
|
-
cwd:
|
|
251
|
-
shell:
|
|
307
|
+
cwd: mergedOptions.cwd,
|
|
308
|
+
shell: isPlatformWindows(),
|
|
252
309
|
isLongRunning: longRunning
|
|
253
310
|
};
|
|
254
|
-
const spawnResult = await spawnAsyncInternal(
|
|
311
|
+
const spawnResult = await spawnAsyncInternal('docker', spawnArgs, spawnOptions);
|
|
255
312
|
if (spawnResult.code !== 0) {
|
|
256
313
|
throw new Error(`docker compose command failed with code ${spawnResult.code}`);
|
|
257
314
|
}
|
|
258
315
|
}
|
|
259
316
|
/**
|
|
260
|
-
* Splits a string into lines, removing empty lines
|
|
317
|
+
* Splits a string into lines, removing `\n` and `\r` characters. Does not return empty lines. Also see {@link stringToLines}.
|
|
261
318
|
* @param str String to split into lines
|
|
262
319
|
* @returns An array of lines from the string, with empty lines removed
|
|
263
320
|
*/
|
|
@@ -265,7 +322,18 @@ export function stringToNonEmptyLines(str) {
|
|
|
265
322
|
if (!str) {
|
|
266
323
|
return [];
|
|
267
324
|
}
|
|
268
|
-
return str.split('\n').filter(line => line
|
|
325
|
+
return str.split('\n').filter(line => line?.trim()).map(line => line.replace('\r', ''));
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Splits a string into lines, removing `\n` and `\r` characters. Returns empty lines. Also see {@link stringToNonEmptyLines}.
|
|
329
|
+
* @param str String to split into lines
|
|
330
|
+
* @returns An array of lines from the string, with empty lines removed
|
|
331
|
+
*/
|
|
332
|
+
export function stringToLines(str) {
|
|
333
|
+
if (!str) {
|
|
334
|
+
return [];
|
|
335
|
+
}
|
|
336
|
+
return str.split('\n').map(line => line.replace('\r', ''));
|
|
269
337
|
}
|
|
270
338
|
/**
|
|
271
339
|
* Runs the requested command using NodeJS spawnSync wrapped in an outer Windows CMD.exe command and returns the result with stdout split into lines.
|
|
@@ -273,6 +341,10 @@ export function stringToNonEmptyLines(str) {
|
|
|
273
341
|
* Use this for simple quick commands that don't require a lot of control.
|
|
274
342
|
*
|
|
275
343
|
* For commands that aren't Windows and CMD specific, use {@link simpleSpawnSync}.
|
|
344
|
+
*
|
|
345
|
+
* **Warning:** Do NOT use this for generating commands dynamically from user input as it could be used to execute arbitrary code.
|
|
346
|
+
* This is meant solely for building up known commands that are not made up of unsanitized user input, and only at compile time.
|
|
347
|
+
* See {@link winInstallCert} and {@link winUninstallCert} for examples of taking user input and inserting it safely into known commands.
|
|
276
348
|
* @param command Command to run
|
|
277
349
|
* @param args Arguments to pass to the command
|
|
278
350
|
* @returns An object with the status code, stdout, stderr, and error (if any)
|
|
@@ -282,7 +354,30 @@ export function simpleCmdSync(command, args, throwOnNonZero = true) {
|
|
|
282
354
|
if (!isPlatformWindows()) {
|
|
283
355
|
throw new Error('getCmdResult is only supported on Windows');
|
|
284
356
|
}
|
|
285
|
-
|
|
357
|
+
// Was previously spawning 'cmd' directly with params '/D', '/S', '/C' - but we may as well let NodeJS do the work of escaping args to work correctly with cmd
|
|
358
|
+
return simpleSpawnSyncInternal(command, args, throwOnNonZero, true);
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Runs the requested command using {@link spawnAsync} wrapped in an outer Windows CMD.exe command and returns the result with stdout split into lines.
|
|
362
|
+
*
|
|
363
|
+
* Use this for simple quick commands that don't require a lot of control.
|
|
364
|
+
*
|
|
365
|
+
* For commands that aren't Windows and CMD specific, use {@link simpleSpawnAsync}.
|
|
366
|
+
*
|
|
367
|
+
* **Warning:** Do NOT use this for generating commands dynamically from user input as it could be used to execute arbitrary code.
|
|
368
|
+
* This is meant solely for building up known commands that are not made up of unsanitized user input, and only at compile time.
|
|
369
|
+
* See {@link winInstallCert} and {@link winUninstallCert} for examples of taking user input and inserting it safely into known commands.
|
|
370
|
+
* @param command Command to run
|
|
371
|
+
* @param args Arguments to pass to the command
|
|
372
|
+
* @returns An object with the status code, stdout, stderr, and error (if any)
|
|
373
|
+
* @throws {@link SimpleSpawnError} if the command fails and throwOnNonZero is true
|
|
374
|
+
*/
|
|
375
|
+
export async function simpleCmdAsync(command, args, throwOnNonZero = true) {
|
|
376
|
+
if (!isPlatformWindows()) {
|
|
377
|
+
throw new Error('getCmdResult is only supported on Windows');
|
|
378
|
+
}
|
|
379
|
+
// Was previously spawning 'cmd' directly with params '/D', '/S', '/C' - but we may as well let NodeJS do the work of escaping args to work correctly with cmd
|
|
380
|
+
return await simpleSpawnAsyncInternal(command, args, throwOnNonZero, true);
|
|
286
381
|
}
|
|
287
382
|
/**
|
|
288
383
|
* Runs the requested command using NodeJS spawnSync and returns the result with stdout split into lines.
|
|
@@ -290,26 +385,35 @@ export function simpleCmdSync(command, args, throwOnNonZero = true) {
|
|
|
290
385
|
* Use this for simple quick commands that don't require a lot of control.
|
|
291
386
|
*
|
|
292
387
|
* For commands that are Windows and CMD specific, use {@link simpleCmdSync}.
|
|
388
|
+
*
|
|
389
|
+
* **Warning:** Do NOT use this for generating commands dynamically from user input as it could be used to execute arbitrary code.
|
|
390
|
+
* This is meant solely for building up known commands that are not made up of unsanitized user input, and only at compile time.
|
|
391
|
+
* See {@link winInstallCert} and {@link winUninstallCert} for examples of taking user input and inserting it safely into known commands.
|
|
293
392
|
* @param command Command to run
|
|
294
393
|
* @param args Arguments to pass to the command
|
|
295
394
|
* @returns An object with the status code, stdout, stderr, and error (if any)
|
|
296
395
|
* @throws {@link SimpleSpawnError} if the command fails and throwOnNonZero is true
|
|
297
396
|
*/
|
|
298
397
|
export function simpleSpawnSync(command, args, throwOnNonZero = true) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
398
|
+
return simpleSpawnSyncInternal(command, args, throwOnNonZero);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Runs the requested command using {@link spawnAsync} and returns the result with stdout split into lines.
|
|
402
|
+
*
|
|
403
|
+
* Use this for simple quick commands that don't require a lot of control.
|
|
404
|
+
*
|
|
405
|
+
* For commands that are Windows and CMD specific, use {@link simpleCmdSync}.
|
|
406
|
+
*
|
|
407
|
+
* **Warning:** Do NOT use this for generating commands dynamically from user input as it could be used to execute arbitrary code.
|
|
408
|
+
* This is meant solely for building up known commands that are not made up of unsanitized user input, and only at compile time.
|
|
409
|
+
* See {@link winInstallCert} and {@link winUninstallCert} for examples of taking user input and inserting it safely into known commands.
|
|
410
|
+
* @param command Command to run
|
|
411
|
+
* @param args Arguments to pass to the command
|
|
412
|
+
* @returns An object with the status code, stdout, stderr, and error (if any)
|
|
413
|
+
* @throws {@link SimpleSpawnError} if the command fails and throwOnNonZero is true
|
|
414
|
+
*/
|
|
415
|
+
export async function simpleSpawnAsync(command, args, throwOnNonZero = true) {
|
|
416
|
+
return await simpleSpawnAsyncInternal(command, args, throwOnNonZero);
|
|
313
417
|
}
|
|
314
418
|
/**
|
|
315
419
|
* @returns `true` if platform() is 'win32', `false` otherwise
|
|
@@ -326,39 +430,32 @@ export function isPlatformMac() {
|
|
|
326
430
|
}
|
|
327
431
|
/**
|
|
328
432
|
*
|
|
329
|
-
* @returns `true` if {@link isPlatformWindows} and {@link isPlatformMac} are both `false, otherwise returns `
|
|
433
|
+
* @returns `true` if {@link isPlatformWindows} and {@link isPlatformMac} are both `false, otherwise returns `true`
|
|
330
434
|
*/
|
|
331
435
|
export function isPlatformLinux() {
|
|
332
436
|
return !isPlatformWindows() && !isPlatformMac();
|
|
333
437
|
}
|
|
334
438
|
/**
|
|
335
439
|
* This is a cross-platform method to get the location of a system command. Useful for checking if software
|
|
336
|
-
* is installed, where it's installed and whether there are multiple locations
|
|
440
|
+
* is installed, where it's installed and whether there are multiple locations.
|
|
441
|
+
* @param commandName The name of the command to find
|
|
442
|
+
* @returns The location of the command, any additional locations, and an error if one occurred
|
|
443
|
+
*/
|
|
444
|
+
export async function which(commandName) {
|
|
445
|
+
return whichInternal(commandName, simpleCmdAsync, simpleSpawnAsync);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* This is a cross-platform method to get the location of a system command. Useful for checking if software
|
|
449
|
+
* is installed, where it's installed and whether there are multiple locations.
|
|
337
450
|
* @param commandName The name of the command to find
|
|
338
451
|
* @returns The location of the command, any additional locations, and an error if one occurred
|
|
339
452
|
*/
|
|
340
453
|
export function whichSync(commandName) {
|
|
341
|
-
|
|
342
|
-
const result = simpleCmdSync('where', [commandName]);
|
|
343
|
-
return {
|
|
344
|
-
location: result.stdoutLines[0],
|
|
345
|
-
additionalLocations: result.stdoutLines.slice(1),
|
|
346
|
-
error: result.error
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
else {
|
|
350
|
-
const result = simpleSpawnSync('which', ['-a', commandName]);
|
|
351
|
-
return {
|
|
352
|
-
location: result.stdoutLines[0],
|
|
353
|
-
additionalLocations: result.stdoutLines.slice(1),
|
|
354
|
-
error: result.error
|
|
355
|
-
};
|
|
356
|
-
}
|
|
454
|
+
return whichInternal(commandName, simpleCmdSync, simpleSpawnSync);
|
|
357
455
|
}
|
|
358
456
|
/**
|
|
359
|
-
* First checks if docker is installed and if not immediately returns false.
|
|
360
|
-
*
|
|
361
|
-
* Then runs the `docker info` command and looks for "error during connect" in the output to determine if docker is running.
|
|
457
|
+
* First checks if docker is installed and if not immediately returns false. Then runs the `docker info`
|
|
458
|
+
* command and looks for "error during connect" in the output to determine if docker is running.
|
|
362
459
|
* @returns `true` if docker is installed and running, `false` otherwise
|
|
363
460
|
*/
|
|
364
461
|
export async function isDockerRunning() {
|
|
@@ -366,21 +463,13 @@ export async function isDockerRunning() {
|
|
|
366
463
|
trace('whichSync will not check if docker is running because docker does not appear to be installed - returning false');
|
|
367
464
|
return false;
|
|
368
465
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
resolve(false);
|
|
377
|
-
}
|
|
378
|
-
else {
|
|
379
|
-
resolve(true);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
});
|
|
383
|
-
});
|
|
466
|
+
try {
|
|
467
|
+
const result = await simpleSpawnAsync('docker', ['info']);
|
|
468
|
+
return !result.stdout.includes('error during connect');
|
|
469
|
+
}
|
|
470
|
+
catch (err) {
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
384
473
|
}
|
|
385
474
|
/**
|
|
386
475
|
* Uses built-in NodeJS readline to ask a question and return the user's answer.
|
|
@@ -408,10 +497,10 @@ export function getConfirmation(question) {
|
|
|
408
497
|
output: process.stdout,
|
|
409
498
|
});
|
|
410
499
|
return new Promise((resolve) => {
|
|
411
|
-
rl.question(`\n
|
|
500
|
+
rl.question(`\n ${Emoji.RedQuestion} ${question}\n ${Emoji.RightArrow} Proceed? (yes/no): `, (answer) => {
|
|
412
501
|
rl.close();
|
|
413
502
|
const confirmed = answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes';
|
|
414
|
-
log(confirmed ?
|
|
503
|
+
log(confirmed ? ` ${Emoji.GreenCheck} Proceeding\n` : ` ${Emoji.RedX} Aborting\n`);
|
|
415
504
|
resolve(confirmed);
|
|
416
505
|
});
|
|
417
506
|
});
|
|
@@ -541,19 +630,8 @@ export async function deleteEnvIfExists(envPath) {
|
|
|
541
630
|
* @returns A Promise that resolves to an array of file paths that match the pattern
|
|
542
631
|
*/
|
|
543
632
|
export async function findFilesRecursively(dir, filenamePattern, options) {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
if (filenamePattern.length > 50) {
|
|
547
|
-
throw new Error(`filenamePattern param must have fewer than 50 characters`);
|
|
548
|
-
}
|
|
549
|
-
const numWildcards = filenamePattern.replace(/\*+/g, '*').split('*').length - 1;
|
|
550
|
-
if (numWildcards > 5) {
|
|
551
|
-
throw new Error(`filenamePattern param must contain 5 or fewer wildcards`);
|
|
552
|
-
}
|
|
553
|
-
if (filenamePattern.includes('/') || filenamePattern.includes('\\')) {
|
|
554
|
-
throw new Error('filenamePattern param must not contain slashes');
|
|
555
|
-
}
|
|
556
|
-
const defaultOptions = { maxDepth: 5 };
|
|
633
|
+
validateFindFilesRecursivelyParams(dir, filenamePattern);
|
|
634
|
+
const defaultOptions = { maxDepth: 5, excludeDirectoryNames: [], returnForwardSlashRelativePaths: false };
|
|
557
635
|
const mergedOptions = { ...defaultOptions, ...options };
|
|
558
636
|
// Convert the pattern to a regex
|
|
559
637
|
const regex = new RegExp('^' + filenamePattern.split(/\*+/).map(escapeStringForRegex).join('.*') + '$');
|
|
@@ -567,7 +645,7 @@ export async function findFilesRecursively(dir, filenamePattern, options) {
|
|
|
567
645
|
const fullPath = resolve(directory, entry.name);
|
|
568
646
|
if (entry.isDirectory()) {
|
|
569
647
|
// Check if directory is in the exclude list
|
|
570
|
-
if (!mergedOptions.excludeDirectoryNames
|
|
648
|
+
if (!mergedOptions.excludeDirectoryNames?.includes(entry.name)) {
|
|
571
649
|
await searchDirectory(fullPath, depth + 1);
|
|
572
650
|
}
|
|
573
651
|
}
|
|
@@ -588,4 +666,298 @@ export async function findFilesRecursively(dir, filenamePattern, options) {
|
|
|
588
666
|
export function escapeStringForRegex(str) {
|
|
589
667
|
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
590
668
|
}
|
|
591
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhbFV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2dlbmVyYWxVdGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWdCLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUNsRSxPQUFPLEVBQUUsTUFBTSxTQUFTLENBQUE7QUFDeEIsT0FBTyxHQUFHLE1BQU0sa0JBQWtCLENBQUE7QUFDbEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUNsQyxPQUFPLElBQUksRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUN6QyxPQUFPLEtBQUssUUFBUSxNQUFNLFVBQVUsQ0FBQTtBQUNwQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0seUJBQXlCLENBQUE7QUFDaEQsT0FBTyxFQUF3QixPQUFPLEVBQUUseUJBQXlCLEVBQUUsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQTtBQUU1SSxNQUFNLHdDQUF3QyxHQUFHLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFBO0FBRWhIOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsR0FBRyxDQUFDLElBQWEsRUFBRSxHQUFHLFFBQW1CO0lBQ3ZELE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLEdBQUcsUUFBUSxDQUFDLENBQUE7QUFDaEMsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsS0FBSyxDQUFDLElBQWMsRUFBRSxHQUFHLFFBQW1CO0lBQzFELElBQUksTUFBTSxDQUFDLFlBQVksRUFBRTtRQUN2QixNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUE7UUFDeEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsUUFB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
|
|
669
|
+
/**
|
|
670
|
+
* Logs the provided 2-dimensional string array as a formatted table.
|
|
671
|
+
*
|
|
672
|
+
* @param data 2-dimensional string array where the first row is the column headers
|
|
673
|
+
* @example
|
|
674
|
+
*
|
|
675
|
+
* logTable([
|
|
676
|
+
* ['Name', 'Age', 'Country'],
|
|
677
|
+
* ['Alice', '28', 'USA'],
|
|
678
|
+
* ['Bob', '22', 'Canada']
|
|
679
|
+
* ])
|
|
680
|
+
*/
|
|
681
|
+
export function logTable(data) {
|
|
682
|
+
if (data.length === 0 || data[0].length === 0)
|
|
683
|
+
return;
|
|
684
|
+
const numColumns = data[0].length;
|
|
685
|
+
const columnWidths = [];
|
|
686
|
+
for (let i = 0; i < numColumns; i++) {
|
|
687
|
+
columnWidths[i] = Math.max(...data.map(row => row[i]?.length || 0));
|
|
688
|
+
}
|
|
689
|
+
const lineSeparator = columnWidths.map(width => '-'.repeat(width)).join(' + ');
|
|
690
|
+
for (let i = 0; i < data.length; i++) {
|
|
691
|
+
const paddedRowArray = data[i].map((cell, colIdx) => cell.padEnd(columnWidths[colIdx], ' '));
|
|
692
|
+
log(paddedRowArray.join(' | '));
|
|
693
|
+
if (i === 0)
|
|
694
|
+
log(lineSeparator);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* See {@link getPowershellHackArgs}.
|
|
699
|
+
*/
|
|
700
|
+
export const powershellHackPrefix = `$env:PSModulePath = [Environment]::GetEnvironmentVariable('PSModulePath', 'Machine'); `;
|
|
701
|
+
/**
|
|
702
|
+
* Powershell doesn't load the system PSModulePath when running in a non-interactive shell.
|
|
703
|
+
* This is a workaround to set the PSModulePath environment variable to the system value before running a powershell command.
|
|
704
|
+
*
|
|
705
|
+
* **Warning:** Do NOT use this for generating commands dynamically from user input as it could be used to execute arbitrary code.
|
|
706
|
+
* This is meant solely for building up known commands that are not made up of unsanitized user input, and only at compile time.
|
|
707
|
+
* See {@link winInstallCert} and {@link winUninstallCert} for examples of taking user input and inserting it safely into known commands.
|
|
708
|
+
* @param command The powershell command to run
|
|
709
|
+
* @returns An array of arguments to pass to {@link spawnAsync} with the "powershell" command as the first argument
|
|
710
|
+
*/
|
|
711
|
+
export function getPowershellHackArgs(command) {
|
|
712
|
+
return ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', `${powershellHackPrefix}${command}`];
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Returns a humanized string representation of the number of milliseconds using ms, seconds, minutes, or hours.
|
|
716
|
+
* @param milliseconds The number of milliseconds to humanize
|
|
717
|
+
* @returns A humanized string representation of the number
|
|
718
|
+
*/
|
|
719
|
+
export function humanizeTime(milliseconds) {
|
|
720
|
+
let value;
|
|
721
|
+
let unit;
|
|
722
|
+
if (milliseconds < 1000) {
|
|
723
|
+
return `${milliseconds} ms`;
|
|
724
|
+
}
|
|
725
|
+
if (milliseconds < 60000) {
|
|
726
|
+
value = milliseconds / 1000;
|
|
727
|
+
unit = 'second';
|
|
728
|
+
}
|
|
729
|
+
else if (milliseconds < 3600000) {
|
|
730
|
+
value = milliseconds / 60000;
|
|
731
|
+
unit = 'minute';
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
value = milliseconds / 3600000;
|
|
735
|
+
unit = 'hour';
|
|
736
|
+
}
|
|
737
|
+
let stringValue = value.toFixed(2);
|
|
738
|
+
if (stringValue.endsWith('.00')) {
|
|
739
|
+
stringValue = stringValue.slice(0, -3);
|
|
740
|
+
}
|
|
741
|
+
else if (stringValue.endsWith('0')) {
|
|
742
|
+
stringValue = stringValue.slice(0, -1);
|
|
743
|
+
}
|
|
744
|
+
if (stringValue !== '1') {
|
|
745
|
+
unit += 's';
|
|
746
|
+
}
|
|
747
|
+
return `${stringValue} ${unit}`;
|
|
748
|
+
}
|
|
749
|
+
export class ExtendedError extends Error {
|
|
750
|
+
innerError;
|
|
751
|
+
constructor(message, innerError) {
|
|
752
|
+
super(message);
|
|
753
|
+
this.innerError = innerError ?? null;
|
|
754
|
+
Object.setPrototypeOf(this, ExtendedError.prototype);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
export function getHostname(url) {
|
|
758
|
+
requireString('url', url);
|
|
759
|
+
trace(`attempting to convert url to hostname: ${url}`);
|
|
760
|
+
try {
|
|
761
|
+
const encodedUrl = encodeURI(url);
|
|
762
|
+
const parsedUrl = new URL(encodedUrl.startsWith('http') ? encodedUrl : 'https://' + encodedUrl);
|
|
763
|
+
trace(`parsed url: ${parsedUrl}`);
|
|
764
|
+
return parsedUrl.hostname;
|
|
765
|
+
}
|
|
766
|
+
catch (e) {
|
|
767
|
+
throw new ExtendedError("Invalid URL", e);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
export async function isDirectory(path) {
|
|
771
|
+
try {
|
|
772
|
+
const stats = await fsp.stat(path);
|
|
773
|
+
return stats.isDirectory();
|
|
774
|
+
}
|
|
775
|
+
catch (err) {
|
|
776
|
+
trace('error checking idDirectory (returning false)', err);
|
|
777
|
+
return false;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
export function isDirectorySync(path) {
|
|
781
|
+
try {
|
|
782
|
+
const stats = fs.statSync(path);
|
|
783
|
+
return stats.isDirectory();
|
|
784
|
+
}
|
|
785
|
+
catch (err) {
|
|
786
|
+
trace('error checking idDirectory (returning false)', err);
|
|
787
|
+
return false;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* This is a somewhat naive method but is useful if you rarely or never deal with unusual operating systems.
|
|
792
|
+
* @returns `win`, `mac` or `linux`
|
|
793
|
+
*/
|
|
794
|
+
export function getPlatformCode() {
|
|
795
|
+
if (isPlatformWindows()) {
|
|
796
|
+
return 'win';
|
|
797
|
+
}
|
|
798
|
+
if (isPlatformMac()) {
|
|
799
|
+
return 'mac';
|
|
800
|
+
}
|
|
801
|
+
if (isPlatformLinux()) {
|
|
802
|
+
return 'linux';
|
|
803
|
+
}
|
|
804
|
+
throw new Error('unrecognized platform: ' + platform());
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Tries connecting to a port to see if it's being listened on or not. It's likely that this won't work in a lot of scenarios, so use it at your own risk.
|
|
808
|
+
* @param port The port to check
|
|
809
|
+
* @returns `true` if the port is available, `false` otherwise
|
|
810
|
+
*/
|
|
811
|
+
export async function isPortAvailable(port) {
|
|
812
|
+
return new Promise((resolve) => {
|
|
813
|
+
const tester = net.connect(port, '127.0.0.1');
|
|
814
|
+
tester.on('connect', () => {
|
|
815
|
+
tester.destroy();
|
|
816
|
+
resolve(false); // port is in use
|
|
817
|
+
});
|
|
818
|
+
tester.on('error', (err) => {
|
|
819
|
+
tester.destroy();
|
|
820
|
+
if (err.code === 'ECONNREFUSED') {
|
|
821
|
+
resolve(true); // port is available
|
|
822
|
+
}
|
|
823
|
+
else {
|
|
824
|
+
resolve(false); // some other error occurred, assume port is in use
|
|
825
|
+
}
|
|
826
|
+
});
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Returns the value for an environment variable or throws if it's undefined or null. Pass optional {@param throwOnEmpty} to throw when the key exists but has an empty value.
|
|
831
|
+
* @param varName The name of the environment variable to get.
|
|
832
|
+
* @param throwOnEmpty Throw an error if key exists (not undefined or null) but is empty.
|
|
833
|
+
* @returns
|
|
834
|
+
*/
|
|
835
|
+
export function getRequiredEnvVar(varName, throwOnEmpty = true) {
|
|
836
|
+
requireString('varName', varName);
|
|
837
|
+
const val = process.env[varName];
|
|
838
|
+
if (val === undefined || val === null) {
|
|
839
|
+
throw new Error(`Missing required environment variable: ${varName}`);
|
|
840
|
+
}
|
|
841
|
+
if (throwOnEmpty && val.trim() === '') {
|
|
842
|
+
throw new Error(`Required environment variable is empty: ${varName}`);
|
|
843
|
+
}
|
|
844
|
+
return val;
|
|
845
|
+
}
|
|
846
|
+
export function getNormalizedError(err) {
|
|
847
|
+
let lastErrorAsError;
|
|
848
|
+
if (err === undefined || err === null) {
|
|
849
|
+
lastErrorAsError = new Error('lastError was undefined or null');
|
|
850
|
+
}
|
|
851
|
+
else if (err instanceof Error) {
|
|
852
|
+
lastErrorAsError = err;
|
|
853
|
+
}
|
|
854
|
+
else if (typeof err === 'string') {
|
|
855
|
+
lastErrorAsError = new Error(err);
|
|
856
|
+
}
|
|
857
|
+
else if (err instanceof Object) {
|
|
858
|
+
try {
|
|
859
|
+
lastErrorAsError = new Error(JSON.stringify(err));
|
|
860
|
+
}
|
|
861
|
+
catch (jsonError) {
|
|
862
|
+
lastErrorAsError = new Error('Object could not be serialized - could not normalize');
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
else {
|
|
866
|
+
lastErrorAsError = new Error(`Unknown error of type ${typeof err} - could not normalize`);
|
|
867
|
+
}
|
|
868
|
+
return lastErrorAsError;
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Call a function until it succeeds. Will stop after the number of calls specified by {@param maxCalls}, or forever if -1 is passed.
|
|
872
|
+
* @param func The function to call
|
|
873
|
+
* @param maxCalls The maximum number of times to call the function before giving up. Pass -1 to retry forever.
|
|
874
|
+
* @param delayMilliseconds The number of milliseconds to wait between calls
|
|
875
|
+
* @param options Options for controlling the behavior of the retry. See {@link WithRetryOptions}.
|
|
876
|
+
*/
|
|
877
|
+
export async function withRetryAsync(func, maxCalls, delayMilliseconds, options) {
|
|
878
|
+
let attemptNumber = 0;
|
|
879
|
+
let lastError;
|
|
880
|
+
const forever = maxCalls === -1;
|
|
881
|
+
const defaultOptions = { initialDelayMilliseconds: 0, traceEnabled: false };
|
|
882
|
+
const mergedOptions = { ...defaultOptions, ...options };
|
|
883
|
+
const shouldLog = config.traceEnabled || mergedOptions.traceEnabled;
|
|
884
|
+
const retryLog = shouldLog ? log : () => { };
|
|
885
|
+
const funcName = mergedOptions.functionLabel ?? func.name ?? 'anonymous';
|
|
886
|
+
if (mergedOptions.initialDelayMilliseconds > 0) {
|
|
887
|
+
retryLog(`initialDelayMilliseconds set to ${mergedOptions.initialDelayMilliseconds} - waiting before first try`);
|
|
888
|
+
await sleep(mergedOptions.initialDelayMilliseconds);
|
|
889
|
+
}
|
|
890
|
+
// eslint-disable-next-line no-constant-condition
|
|
891
|
+
while (true) {
|
|
892
|
+
attemptNumber++;
|
|
893
|
+
retryLog(`calling ${funcName} - attempt number ${attemptNumber}`);
|
|
894
|
+
try {
|
|
895
|
+
await func();
|
|
896
|
+
retryLog(`attempt ${attemptNumber} was successful`);
|
|
897
|
+
break;
|
|
898
|
+
}
|
|
899
|
+
catch (err) {
|
|
900
|
+
if (shouldLog) {
|
|
901
|
+
console.error(err);
|
|
902
|
+
}
|
|
903
|
+
lastError = err;
|
|
904
|
+
}
|
|
905
|
+
if (!forever && attemptNumber === maxCalls) {
|
|
906
|
+
throw new ExtendedError(`Failed to run method with retry after ${maxCalls} attempts`, getNormalizedError(lastError));
|
|
907
|
+
}
|
|
908
|
+
retryLog(`attempt number ${attemptNumber} failed - waiting ${delayMilliseconds} milliseconds before trying again`);
|
|
909
|
+
await sleep(delayMilliseconds);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Collapses each instance of consecutive whitespace characters into a single space.
|
|
914
|
+
*/
|
|
915
|
+
export function collapseWhitespace(str) {
|
|
916
|
+
return str.replace(/\s+/g, ' ');
|
|
917
|
+
}
|
|
918
|
+
/**
|
|
919
|
+
* Check if a string is a valid directory name. This is a very simple check that just makes sure the string doesn't contain any invalid characters.
|
|
920
|
+
* @param dirName The directory name to check
|
|
921
|
+
* @returns `true` if the directory name is valid, `false` otherwise
|
|
922
|
+
*/
|
|
923
|
+
export function isValidDirName(dirName) {
|
|
924
|
+
// List of generally invalid characters for directory names in Windows, macOS, and Linux
|
|
925
|
+
const invalidChars = ['<', '>', ':', '"', '/', '\\', '|', '?', '*'];
|
|
926
|
+
for (const char of dirName) {
|
|
927
|
+
if (invalidChars.includes(char) || char.charCodeAt(0) <= 31) {
|
|
928
|
+
return false;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
return true;
|
|
932
|
+
}
|
|
933
|
+
export function hasWhitespace(str) {
|
|
934
|
+
return /\s/.test(str);
|
|
935
|
+
}
|
|
936
|
+
export function stripShellMetaCharacters(input) {
|
|
937
|
+
const metaCharacters = [
|
|
938
|
+
'\\', '`', '$', '"', "'", '<', '>', '|', ';', ' ',
|
|
939
|
+
'&', '(', ')', '[', ']', '{', '}', '?', '*', '#', '~', '^'
|
|
940
|
+
];
|
|
941
|
+
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
942
|
+
const regex = new RegExp(`[${metaCharacters.map(escapeRegex).join('')}]`, 'g');
|
|
943
|
+
return input.replace(regex, '');
|
|
944
|
+
}
|
|
945
|
+
export var Emoji;
|
|
946
|
+
(function (Emoji) {
|
|
947
|
+
Emoji["RightArrow"] = "\u27A1\uFE0F";
|
|
948
|
+
Emoji["LeftArrow"] = "\u2B05\uFE0F";
|
|
949
|
+
Emoji["GreenCheck"] = "\u2705";
|
|
950
|
+
Emoji["Warning"] = "\u26A0\uFE0F";
|
|
951
|
+
Emoji["Lightning"] = "\u26A1";
|
|
952
|
+
Emoji["Exclamation"] = "\u2757";
|
|
953
|
+
Emoji["RedQuestion"] = "\u2753";
|
|
954
|
+
Emoji["RedX"] = "\u274C";
|
|
955
|
+
Emoji["Info"] = "\u2139\uFE0F";
|
|
956
|
+
Emoji["SadFace"] = "\uD83D\uDE22";
|
|
957
|
+
Emoji["Tools"] = "\uD83D\uDEE0\uFE0F";
|
|
958
|
+
Emoji["NoEntry"] = "\u26D4";
|
|
959
|
+
Emoji["Stop"] = "\uD83D\uDED1";
|
|
960
|
+
Emoji["Certificate"] = "\uD83D\uDCDC";
|
|
961
|
+
Emoji["Key"] = "\uD83D\uDD11";
|
|
962
|
+
})(Emoji || (Emoji = {}));
|
|
963
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhbFV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2dlbmVyYWxVdGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsTUFBTSxTQUFTLENBQUE7QUFDeEIsT0FBTyxHQUFHLE1BQU0sa0JBQWtCLENBQUE7QUFDbEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUNsQyxPQUFPLElBQUksRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUN6QyxPQUFPLEtBQUssUUFBUSxNQUFNLFVBQVUsQ0FBQTtBQUNwQyxPQUFPLEtBQUssR0FBRyxNQUFNLEtBQUssQ0FBQTtBQUMxQixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0seUJBQXlCLENBQUE7QUFDaEQsT0FBTyxFQUF3QixPQUFPLEVBQUUseUJBQXlCLEVBQUUsa0JBQWtCLEVBQUUsd0JBQXdCLEVBQUUsdUJBQXVCLEVBQUUsa0JBQWtCLEVBQUUsa0NBQWtDLEVBQUUsYUFBYSxFQUFFLE1BQU0sMkJBQTJCLENBQUE7QUFNbFAsTUFBTSx3Q0FBd0MsR0FBRyxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQTtBQUVoSDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLEdBQUcsQ0FBQyxJQUFhLEVBQUUsR0FBRyxRQUFtQjtJQUN2RCxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLFFBQVEsQ0FBQyxDQUFBO0FBQ2hDLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLEtBQUssQ0FBQyxTQUFrQixFQUFFLElBQWEsRUFBRSxHQUFHLFFBQW1CO0lBQzdFLElBQUksU0FBUyxFQUFFO1FBQ2IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxRQUFRLENBQUMsQ0FBQTtL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
|