@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.
Files changed (81) hide show
  1. package/dist/cjs/DependencyChecker.d.ts +26 -0
  2. package/dist/cjs/DependencyChecker.d.ts.map +1 -0
  3. package/dist/cjs/DependencyChecker.js +200 -0
  4. package/dist/cjs/GitUtility.d.ts +7 -0
  5. package/dist/cjs/GitUtility.d.ts.map +1 -0
  6. package/dist/cjs/GitUtility.js +49 -0
  7. package/dist/cjs/NixUtil.d.ts +8 -0
  8. package/dist/cjs/NixUtil.d.ts.map +1 -0
  9. package/dist/cjs/NixUtil.js +50 -0
  10. package/dist/cjs/TarballUtility.d.ts +17 -7
  11. package/dist/cjs/TarballUtility.d.ts.map +1 -1
  12. package/dist/cjs/TarballUtility.js +18 -24
  13. package/dist/cjs/certUtils.d.ts +53 -17
  14. package/dist/cjs/certUtils.d.ts.map +1 -1
  15. package/dist/cjs/certUtils.js +176 -111
  16. package/dist/cjs/colors.d.ts +17 -0
  17. package/dist/cjs/colors.d.ts.map +1 -0
  18. package/dist/cjs/colors.js +30 -0
  19. package/dist/cjs/dbMigrationUtils.js +44 -54
  20. package/dist/cjs/dotnetUtils.d.ts.map +1 -1
  21. package/dist/cjs/dotnetUtils.js +4 -2
  22. package/dist/cjs/esmSpecific.d.mts +5 -0
  23. package/dist/cjs/esmSpecific.d.mts.map +1 -1
  24. package/dist/cjs/esmSpecific.mjs +6 -1
  25. package/dist/cjs/generalUtils.d.ts +252 -26
  26. package/dist/cjs/generalUtils.d.ts.map +1 -1
  27. package/dist/cjs/generalUtils.js +503 -107
  28. package/dist/cjs/generalUtilsInternal.d.ts +9 -3
  29. package/dist/cjs/generalUtilsInternal.d.ts.map +1 -1
  30. package/dist/cjs/generalUtilsInternal.js +160 -59
  31. package/dist/cjs/hostFileUtils.d.ts +18 -0
  32. package/dist/cjs/hostFileUtils.d.ts.map +1 -0
  33. package/dist/cjs/hostFileUtils.js +100 -0
  34. package/dist/cjs/index.d.ts +1 -0
  35. package/dist/cjs/index.d.ts.map +1 -1
  36. package/dist/cjs/index.js +2 -1
  37. package/dist/cjs/runWhileParentAlive.js +7 -9
  38. package/dist/cjs/testUtils.d.ts +11 -0
  39. package/dist/cjs/testUtils.d.ts.map +1 -0
  40. package/dist/cjs/testUtils.js +58 -0
  41. package/dist/esm/DependencyChecker.d.ts +26 -0
  42. package/dist/esm/DependencyChecker.d.ts.map +1 -0
  43. package/dist/esm/DependencyChecker.js +172 -0
  44. package/dist/esm/GitUtility.d.ts +7 -0
  45. package/dist/esm/GitUtility.d.ts.map +1 -0
  46. package/dist/esm/GitUtility.js +43 -0
  47. package/dist/esm/NixUtil.d.ts +8 -0
  48. package/dist/esm/NixUtil.d.ts.map +1 -0
  49. package/dist/esm/NixUtil.js +46 -0
  50. package/dist/esm/TarballUtility.d.ts +17 -7
  51. package/dist/esm/TarballUtility.d.ts.map +1 -1
  52. package/dist/esm/TarballUtility.js +21 -25
  53. package/dist/esm/certUtils.d.ts +53 -17
  54. package/dist/esm/certUtils.d.ts.map +1 -1
  55. package/dist/esm/certUtils.js +173 -86
  56. package/dist/esm/colors.d.ts +17 -0
  57. package/dist/esm/colors.d.ts.map +1 -0
  58. package/dist/esm/colors.js +20 -0
  59. package/dist/esm/dbMigrationUtils.js +45 -55
  60. package/dist/esm/dotnetUtils.d.ts.map +1 -1
  61. package/dist/esm/dotnetUtils.js +4 -2
  62. package/dist/esm/esmSpecific.d.mts +5 -0
  63. package/dist/esm/esmSpecific.d.mts.map +1 -1
  64. package/dist/esm/esmSpecific.mjs +6 -1
  65. package/dist/esm/generalUtils.d.ts +252 -26
  66. package/dist/esm/generalUtils.d.ts.map +1 -1
  67. package/dist/esm/generalUtils.js +477 -105
  68. package/dist/esm/generalUtilsInternal.d.ts +9 -3
  69. package/dist/esm/generalUtilsInternal.d.ts.map +1 -1
  70. package/dist/esm/generalUtilsInternal.js +151 -57
  71. package/dist/esm/hostFileUtils.d.ts +18 -0
  72. package/dist/esm/hostFileUtils.d.ts.map +1 -0
  73. package/dist/esm/hostFileUtils.js +85 -0
  74. package/dist/esm/index.d.ts +1 -0
  75. package/dist/esm/index.d.ts.map +1 -1
  76. package/dist/esm/index.js +2 -1
  77. package/dist/esm/runWhileParentAlive.js +8 -10
  78. package/dist/esm/testUtils.d.ts +11 -0
  79. package/dist/esm/testUtils.d.ts.map +1 -0
  80. package/dist/esm/testUtils.js +47 -0
  81. package/package.json +38 -2
@@ -1,30 +1,66 @@
1
+ /** Control what is logged when running certUtils functions. */
2
+ export interface CertLogOptions {
3
+ logSpawnOutput: boolean;
4
+ logTraceMessages: boolean;
5
+ logElevatedPermissionsMessage: boolean;
6
+ logSuccess: boolean;
7
+ }
8
+ export interface GenerateCertOptions extends CertLogOptions {
9
+ /** The directory to write the generated cert files to. Defaults to `./cert`. */
10
+ outputDirectory: string;
11
+ }
12
+ /** Subject, thumbprint or path to the pfx file. Used with the {@link winUninstallCert} function. */
13
+ export type CertIdentifier = string | {
14
+ thumbprint: string;
15
+ } | {
16
+ pfxPath: string;
17
+ };
18
+ /** The subject or path to the pfx file. Used with the {@link winCertIsInstalled} function. */
19
+ export type CertIdentifierWithoutThumbprint = string | {
20
+ pfxPath: string;
21
+ };
22
+ /** Cert info returned by {@link winGetPfxInfo}. */
23
+ export type CertInfo = {
24
+ subject: string;
25
+ thumbprint: string;
26
+ pfxPath: string;
27
+ };
1
28
  /**
2
29
  * Wrapper function for calling openssl to generate a self-signed cert to be used for developing a local website with trusted https.
3
30
  * @param url The url to generate a cert for. This will be used as the common name (CN) in the cert as well as the filename for the generated cert files.
4
- * @param outputDirectory The directory to write the generated cert files to. Defaults to './cert'.
31
+ * @param options Options for generating the cert.
32
+ * @returns The path to the generated pfx file.
5
33
  */
6
- export declare function generateCertWithOpenSsl(url: string, outputDirectory?: string): Promise<void>;
34
+ export declare function generateCertWithOpenSsl(url: string, options?: Partial<GenerateCertOptions>): Promise<string>;
7
35
  /**
8
- * Uses Powershell to install a cert to the local machine's trusted root store. Must have admin permissions.
9
- *
10
- * If the cert is already installed, this method will do nothing.
11
- * @param urlOrCertFilename The url or cert filename to install. The url + '.pfx' or the cert filename passed must match a file that exists in the certDirectory.
12
- * @param certDirectory The directory to look for the cert file in. Defaults to './cert'.
36
+ * Uses Powershell to install a cert to the local machine's trusted root store. Must have elevated permissions.
37
+ * If the cert is already installed, this function will do nothing.
38
+ * @param pfxPath The path to the pfx file to install.
13
39
  */
14
- export declare function winInstallCert(urlOrCertFilename: string, certDirectory?: string): Promise<void>;
40
+ export declare function winInstallCert(pfxPath: string, options?: Partial<CertLogOptions>): Promise<void>;
15
41
  /**
16
- * Uses Powershell to uninstall a cert from the local machine's trusted root store. Must have admin permissions.
17
- * @param urlOrSubject The url or subject of the cert to uninstall. If the cert was installed with the winInstallCert method, this will be the url passed to that method.
42
+ * Uses Powershell to check if a cert is already installed to the local machine's trusted root store.
43
+ * Uses the subject of the cert in order to avoid false negatives from regenerating the same self-signed cert
44
+ * with the same subject but different thumbprint. Note that this method is geared towards use with certs generated
45
+ * with the {@link generateCertWithOpenSsl} function, so this may not work using subject if your subject is not precisely "`CN=<url>`".
46
+ * @param identifier The subject or path to the pfx file of the cert to check.
47
+ * @returns `true` if the cert is already installed, `false` otherwise.
18
48
  */
19
- export declare function winUninstallCert(urlOrSubject: string): Promise<void>;
49
+ export declare function winCertIsInstalled(identifier: CertIdentifierWithoutThumbprint, options?: Partial<CertLogOptions>): Promise<boolean>;
20
50
  /**
21
- * Does not actually do anything - just outputs the manual instructions for installing a cert for use by chrome on linux.
51
+ * Uses Powershell to uninstall a cert from the local machine's trusted root store. Must have elevated permissions.
52
+ * @param identifier The subject, thumbprint or path to the pfx file of the cert to uninstall.
53
+ * @param options Options for uninstalling the cert.
22
54
  */
23
- export declare function linuxInstallCert(): void;
55
+ export declare function winUninstallCert(identifier: CertIdentifier, options?: Partial<CertLogOptions>): Promise<void>;
24
56
  /**
25
- * Uses Powershell to check if a cert is already installed to the local machine's trusted root store.
26
- * @param urlOrSubject The url or subject of the cert to check. If the cert was installed with the winInstallCert method, this will be the url passed to that method.
27
- * @returns `true` if the cert is already installed, `false` otherwise.
57
+ * Uses Powershell to get info about a cert.
58
+ * @param pfxPath The path to the pfx file to get info for.
59
+ * @returns The subject, thumbprint and pfxPath of the cert.
28
60
  */
29
- export declare function winCertAlreadyInstalled(urlOrSubject: string): Promise<boolean>;
61
+ export declare function winGetPfxInfo(pfxPath: string): Promise<CertInfo>;
62
+ /**
63
+ * Does not actually do anything - just outputs the manual instructions for installing a cert for use by chrome on linux.
64
+ */
65
+ export declare function linuxInstallCert(): void;
30
66
  //# sourceMappingURL=certUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"certUtils.d.ts","sourceRoot":"","sources":["../../src/certUtils.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,eAAe,GAAE,MAAiB,iBAuD5F;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,iBAAiB,EAAE,MAAM,EAAE,aAAa,SAAW,iBA8BvF;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,YAAY,EAAE,MAAM,iBAY1D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,SAU/B;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAmBpF"}
1
+ {"version":3,"file":"certUtils.d.ts","sourceRoot":"","sources":["../../src/certUtils.ts"],"names":[],"mappings":"AAqBA,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,OAAO,CAAA;IACvB,gBAAgB,EAAE,OAAO,CAAA;IACzB,6BAA6B,EAAE,OAAO,CAAA;IACtC,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,mBAAoB,SAAQ,cAAc;IACzD,gFAAgF;IAChF,eAAe,EAAE,MAAM,CAAA;CACxB;AASD,oGAAoG;AACpG,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAElF,8FAA8F;AAC9F,MAAM,MAAM,+BAA+B,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1E,mDAAmD;AACnD,MAAM,MAAM,QAAQ,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/E;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAkElH;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,iBAwBtF;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,+BAA+B,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAkCzI;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,iBA+BnG;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqBtE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,SAU/B"}
@@ -1,57 +1,40 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.winCertAlreadyInstalled = exports.linuxInstallCert = exports.winUninstallCert = exports.winInstallCert = exports.generateCertWithOpenSsl = void 0;
6
+ exports.linuxInstallCert = exports.winGetPfxInfo = exports.winUninstallCert = exports.winCertIsInstalled = exports.winInstallCert = exports.generateCertWithOpenSsl = void 0;
30
7
  const node_fs_1 = __importDefault(require("node:fs"));
31
8
  const promises_1 = __importDefault(require("node:fs/promises"));
32
9
  const node_path_1 = __importDefault(require("node:path"));
33
- const nodeCliUtils = __importStar(require("./generalUtils.js"));
34
10
  const generalUtils_js_1 = require("./generalUtils.js");
35
- const requiresAdminMessage = `➡️ Important: Requires admin permissions`;
36
- const powershellHackPrefix = `$env:PSModulePath = [Environment]::GetEnvironmentVariable('PSModulePath', 'Machine'); `;
11
+ const colors_js_1 = require("./colors.js");
12
+ const defaultCertLogOptions = {
13
+ logSpawnOutput: false,
14
+ logTraceMessages: false,
15
+ logElevatedPermissionsMessage: true,
16
+ logSuccess: true
17
+ };
37
18
  /**
38
19
  * Wrapper function for calling openssl to generate a self-signed cert to be used for developing a local website with trusted https.
39
20
  * @param url The url to generate a cert for. This will be used as the common name (CN) in the cert as well as the filename for the generated cert files.
40
- * @param outputDirectory The directory to write the generated cert files to. Defaults to './cert'.
21
+ * @param options Options for generating the cert.
22
+ * @returns The path to the generated pfx file.
41
23
  */
42
- async function generateCertWithOpenSsl(url, outputDirectory = './cert') {
43
- nodeCliUtils.requireString('url', url);
24
+ async function generateCertWithOpenSsl(url, options) {
25
+ (0, generalUtils_js_1.requireString)('url', url);
44
26
  throwIfMaybeBadUrlChars(url);
45
- const isMac = nodeCliUtils.isPlatformMac();
46
- const spawnArgs = { cwd: outputDirectory };
47
- (0, generalUtils_js_1.log)('- checking if openssl is installed');
27
+ const isMac = (0, generalUtils_js_1.isPlatformMac)();
28
+ const mergedOptions = { ...defaultCertLogOptions, outputDirectory: './cert', ...options };
29
+ const spawnArgs = { cwd: mergedOptions.outputDirectory, stdio: mergedOptions.logSpawnOutput ? 'inherit' : 'pipe' };
30
+ (0, generalUtils_js_1.logIf)(mergedOptions.logTraceMessages, 'checking if openssl is installed');
48
31
  let brewOpenSslPath = '';
49
32
  if (!isMac) {
50
- const openSslPath = nodeCliUtils.whichSync('openssl').location;
33
+ const openSslPath = (0, generalUtils_js_1.whichSync)('openssl').location;
51
34
  if (!openSslPath) {
52
35
  throw Error('openssl is required but was not found');
53
36
  }
54
- (0, generalUtils_js_1.log)(`- using openssl at: ${openSslPath}`);
37
+ (0, generalUtils_js_1.logIf)(mergedOptions.logTraceMessages, `using openssl at: ${openSslPath}`);
55
38
  }
56
39
  else if (isMac) {
57
40
  const brewOpenSslDirectory = getBrewOpensslPath();
@@ -63,81 +46,154 @@ async function generateCertWithOpenSsl(url, outputDirectory = './cert') {
63
46
  throw Error(`openssl (brew version) is required but was not found at: ${brewOpenSslPath}`);
64
47
  }
65
48
  else {
66
- (0, generalUtils_js_1.log)(`- using openssl at: ${brewOpenSslPath}`);
49
+ (0, generalUtils_js_1.logIf)(mergedOptions.logTraceMessages, `using openssl at: ${brewOpenSslPath}`);
67
50
  }
68
51
  }
69
- nodeCliUtils.ensureDirectory(outputDirectory);
70
- const keyName = url + '.key';
52
+ (0, generalUtils_js_1.ensureDirectory)(mergedOptions.outputDirectory);
71
53
  const crtName = url + '.crt';
54
+ const keyName = url + '.key';
72
55
  const pfxName = url + '.pfx';
73
- const pfxPath = node_path_1.default.join(outputDirectory, pfxName);
74
- if (node_fs_1.default.existsSync(pfxPath)) {
75
- throw Error(`File ${pfxPath} already exists. Delete or rename this file if you want to generate a new cert.`);
56
+ const sanCnfName = url + '.cnf';
57
+ const filesToCheck = [crtName, keyName, pfxName, sanCnfName];
58
+ for (const file of filesToCheck) {
59
+ const filePath = node_path_1.default.join(mergedOptions.outputDirectory, file);
60
+ if (node_fs_1.default.existsSync(filePath)) {
61
+ throw Error(`${generalUtils_js_1.Emoji.Stop} File ${filePath} already exists. Delete or rename all of the following files from '${mergedOptions.outputDirectory}' if you want to generate a new cert: ${filesToCheck.join(', ')}.`);
62
+ }
76
63
  }
77
- (0, generalUtils_js_1.log)('- writing san.cnf file for use with openssl command');
64
+ (0, generalUtils_js_1.logIf)(mergedOptions.logTraceMessages, `writing ${sanCnfName} file for use with openssl command`);
78
65
  const sanCnfContents = getSanCnfFileContents(url);
79
- const sanCnfPath = node_path_1.default.join(outputDirectory, 'san.cnf');
66
+ const sanCnfPath = node_path_1.default.join(mergedOptions.outputDirectory, sanCnfName);
80
67
  await promises_1.default.writeFile(sanCnfPath, sanCnfContents);
81
- (0, generalUtils_js_1.log)(`- attempting to generate cert ${pfxName}`);
82
- const genKeyAndCrtArgs = `req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout ${keyName} -out ${crtName} -subj /CN=${url} -config san.cnf`.split(' ');
68
+ (0, generalUtils_js_1.logIf)(mergedOptions.logTraceMessages, `attempting to generate cert ${pfxName}`);
69
+ const genKeyAndCrtArgs = `req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout ${keyName} -out ${crtName} -subj /CN=${url} -config ${sanCnfName}`.split(' ');
83
70
  const command = isMac ? brewOpenSslPath : 'openssl';
84
- let result = await nodeCliUtils.spawnAsync(command, genKeyAndCrtArgs, spawnArgs);
85
- if (result.code !== 0) {
86
- throw Error(`openssl command to generate key and crt files failed with exit code ${result.code}`);
87
- }
88
- (0, generalUtils_js_1.log)('- converting key and crt to pfx');
71
+ let result = await (0, generalUtils_js_1.spawnAsync)(command, genKeyAndCrtArgs, spawnArgs);
72
+ throwIfSpawnResultError(result);
73
+ (0, generalUtils_js_1.logIf)(mergedOptions.logTraceMessages, 'converting key and crt to pfx');
89
74
  const convertToPfxArgs = `pkcs12 -certpbe AES-256-CBC -export -out ${pfxName} -aes256 -inkey ${keyName} -in ${crtName} -password pass:`.split(' ');
90
- result = await nodeCliUtils.spawnAsync(command, convertToPfxArgs, spawnArgs);
91
- if (result.code !== 0) {
92
- throw Error(`openssl command to convert key and crt files to a pfx failed with exit code ${result.code}`);
93
- }
75
+ result = await (0, generalUtils_js_1.spawnAsync)(command, convertToPfxArgs, spawnArgs);
76
+ throwIfSpawnResultError(result);
77
+ const pfxPath = node_path_1.default.join(mergedOptions.outputDirectory, pfxName);
78
+ (0, generalUtils_js_1.logIf)(mergedOptions.logSuccess, `${generalUtils_js_1.Emoji.GreenCheck} Successfully generated cert: ${pfxPath}`);
79
+ return pfxPath;
94
80
  }
95
81
  exports.generateCertWithOpenSsl = generateCertWithOpenSsl;
96
82
  /**
97
- * Uses Powershell to install a cert to the local machine's trusted root store. Must have admin permissions.
98
- *
99
- * If the cert is already installed, this method will do nothing.
100
- * @param urlOrCertFilename The url or cert filename to install. The url + '.pfx' or the cert filename passed must match a file that exists in the certDirectory.
101
- * @param certDirectory The directory to look for the cert file in. Defaults to './cert'.
83
+ * Uses Powershell to install a cert to the local machine's trusted root store. Must have elevated permissions.
84
+ * If the cert is already installed, this function will do nothing.
85
+ * @param pfxPath The path to the pfx file to install.
102
86
  */
103
- async function winInstallCert(urlOrCertFilename, certDirectory = './cert') {
104
- nodeCliUtils.requireString('urlOrCertFilename', urlOrCertFilename);
105
- nodeCliUtils.requireValidPath('certDirectory', certDirectory);
106
- throwIfMaybeBadUrlChars(urlOrCertFilename, 'urlOrCertFilename');
107
- if (!nodeCliUtils.isPlatformWindows()) {
108
- throw Error('This method is only supported on Windows');
109
- }
110
- (0, generalUtils_js_1.log)(requiresAdminMessage);
111
- if (await winCertAlreadyInstalled(urlOrCertFilename)) {
112
- (0, generalUtils_js_1.log)(`certificate for ${urlOrCertFilename} is already installed - to install it again, first uninstall it manually or with the winUninstallCert method`);
87
+ async function winInstallCert(pfxPath, options) {
88
+ if (!(0, generalUtils_js_1.isPlatformWindows)()) {
89
+ throw Error('winInstallCert is only supported on Windows');
90
+ }
91
+ validatePfxPath(pfxPath);
92
+ const mergedOptions = { ...defaultCertLogOptions, ...options };
93
+ (0, generalUtils_js_1.logIf)(mergedOptions.logElevatedPermissionsMessage, getRequiresElevatedPermissionsMessage(true));
94
+ if (await winCertIsInstalled({ pfxPath }, mergedOptions)) {
95
+ const certInfo = await winGetPfxInfo(pfxPath);
96
+ (0, generalUtils_js_1.logIf)(mergedOptions.logTraceMessages, `${generalUtils_js_1.Emoji.Warning} certificate '${pfxPath}' with subject '${certInfo.subject}' is already installed - to install it again, first uninstall it manually or with the winUninstallCert function`);
113
97
  return;
114
98
  }
115
- const certName = urlOrCertFilename.endsWith('.pfx') ? urlOrCertFilename : urlOrCertFilename + '.pfx';
116
- const certPath = node_path_1.default.join(certDirectory, certName);
117
- if (!node_fs_1.default.existsSync(certPath)) {
118
- throw Error(`File ${certPath} does not exist. Generate this first if you want to install it.`);
99
+ (0, generalUtils_js_1.logIf)(mergedOptions.logTraceMessages, `installing cert '${pfxPath}'`);
100
+ const psCommandArgs = (0, generalUtils_js_1.getPowershellHackArgs)(`Import-PfxCertificate -FilePath '${pfxPath}' -CertStoreLocation Cert:\\LocalMachine\\Root`);
101
+ const result = await (0, generalUtils_js_1.spawnAsync)('powershell', psCommandArgs, { stdio: mergedOptions.logSpawnOutput ? 'inherit' : 'pipe' });
102
+ throwIfSpawnResultError(result);
103
+ (0, generalUtils_js_1.logIf)(mergedOptions.logSuccess, `${generalUtils_js_1.Emoji.GreenCheck} Successfully installed cert: ${pfxPath}`);
104
+ }
105
+ exports.winInstallCert = winInstallCert;
106
+ /**
107
+ * Uses Powershell to check if a cert is already installed to the local machine's trusted root store.
108
+ * Uses the subject of the cert in order to avoid false negatives from regenerating the same self-signed cert
109
+ * with the same subject but different thumbprint. Note that this method is geared towards use with certs generated
110
+ * with the {@link generateCertWithOpenSsl} function, so this may not work using subject if your subject is not precisely "`CN=<url>`".
111
+ * @param identifier The subject or path to the pfx file of the cert to check.
112
+ * @returns `true` if the cert is already installed, `false` otherwise.
113
+ */
114
+ async function winCertIsInstalled(identifier, options) {
115
+ if (!(0, generalUtils_js_1.isPlatformWindows)()) {
116
+ throw new Error('winCertIsInstalled is only supported on Windows');
117
+ }
118
+ const mergedOptions = { ...defaultCertLogOptions, ...options };
119
+ let psCommandArgs;
120
+ // Get the count of certs installed with the same subject as the one we're trying to install
121
+ if (typeof identifier === 'string') {
122
+ (0, generalUtils_js_1.requireString)('subject', identifier);
123
+ validateSubject(identifier);
124
+ const subject = identifier.startsWith('CN=') ? identifier : `CN=${identifier}`;
125
+ psCommandArgs = (0, generalUtils_js_1.getPowershellHackArgs)(`Write-Host (Get-ChildItem Cert:\\LocalMachine\\Root | Where-Object { $_.Subject -eq '${subject}' } | Measure-Object).Count`);
119
126
  }
120
- const psCommand = `${powershellHackPrefix}Import-PfxCertificate -FilePath '${certPath}' -CertStoreLocation Cert:\\LocalMachine\\Root`;
121
- const result = await nodeCliUtils.spawnAsync('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', psCommand]);
122
- if (result.code !== 0) {
123
- throw Error(`powershell command to install cert failed with exit code ${result.code}`);
127
+ else if ('pfxPath' in identifier) {
128
+ validatePfxPath(identifier.pfxPath);
129
+ psCommandArgs = (0, generalUtils_js_1.getPowershellHackArgs)(`Write-Host (Get-ChildItem Cert:\\LocalMachine\\Root | Where-Object { $_.Subject -eq (Get-PfxCertificate -FilePath '${identifier.pfxPath}').Subject } | Measure-Object).Count`);
124
130
  }
131
+ const tracePart = (typeof identifier === 'string') ? `subject ${identifier}` : `pfxPath ${identifier.pfxPath}`;
132
+ (0, generalUtils_js_1.logIf)(mergedOptions.logTraceMessages, `checking if cert with ${tracePart} is already installed`);
133
+ const result = await (0, generalUtils_js_1.spawnAsync)('powershell', psCommandArgs, { stdio: 'pipe' });
134
+ throwIfSpawnResultError(result);
135
+ const lines = (0, generalUtils_js_1.stringToNonEmptyLines)(result.stdout);
136
+ if (lines.length !== 1) {
137
+ throw new Error(`Unexpected output from powershell command to check if the cert is already installed: ${result.stdout}`);
138
+ }
139
+ return lines[0].trim() !== '0';
125
140
  }
126
- exports.winInstallCert = winInstallCert;
141
+ exports.winCertIsInstalled = winCertIsInstalled;
127
142
  /**
128
- * Uses Powershell to uninstall a cert from the local machine's trusted root store. Must have admin permissions.
129
- * @param urlOrSubject The url or subject of the cert to uninstall. If the cert was installed with the winInstallCert method, this will be the url passed to that method.
143
+ * Uses Powershell to uninstall a cert from the local machine's trusted root store. Must have elevated permissions.
144
+ * @param identifier The subject, thumbprint or path to the pfx file of the cert to uninstall.
145
+ * @param options Options for uninstalling the cert.
130
146
  */
131
- async function winUninstallCert(urlOrSubject) {
132
- nodeCliUtils.requireString('urlOrSubject', urlOrSubject);
133
- (0, generalUtils_js_1.log)(requiresAdminMessage);
134
- const psCommand = `${powershellHackPrefix}Get-ChildItem Cert:\\LocalMachine\\Root | Where-Object { $_.Subject -match '${urlOrSubject}' } | Remove-Item`;
135
- const result = await nodeCliUtils.spawnAsync('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', psCommand]);
136
- if (result.code !== 0) {
137
- throw Error(`powershell command to uninstall cert failed with exit code ${result.code}`);
147
+ async function winUninstallCert(identifier, options) {
148
+ if (!(0, generalUtils_js_1.isPlatformWindows)()) {
149
+ throw new Error('winUninstallCert is only supported on Windows');
150
+ }
151
+ const mergedOptions = { ...defaultCertLogOptions, ...options };
152
+ (0, generalUtils_js_1.logIf)(mergedOptions.logElevatedPermissionsMessage, getRequiresElevatedPermissionsMessage(false));
153
+ let psCommandArgs;
154
+ if (typeof identifier === 'string') {
155
+ (0, generalUtils_js_1.requireString)('subject', identifier);
156
+ validateSubject(identifier);
157
+ psCommandArgs = (0, generalUtils_js_1.getPowershellHackArgs)(`Get-ChildItem Cert:\\LocalMachine\\Root | Where-Object { $_.Subject -match '${identifier}' } | Remove-Item`);
158
+ }
159
+ else if ('thumbprint' in identifier) {
160
+ validateNoQuotes('thumbprint', identifier.thumbprint);
161
+ psCommandArgs = (0, generalUtils_js_1.getPowershellHackArgs)(`Get-ChildItem Cert:\\LocalMachine\\Root | Where-Object { $_.Thumbprint -eq '${identifier.thumbprint}' } | Remove-Item`);
162
+ }
163
+ else if ('pfxPath' in identifier) {
164
+ validatePfxPath(identifier.pfxPath);
165
+ psCommandArgs = (0, generalUtils_js_1.getPowershellHackArgs)(`$thumbprint = (Get-PfxCertificate -FilePath '${identifier.pfxPath}').Thumbprint; Get-ChildItem Cert:\\LocalMachine\\Root | Where-Object { $_.Thumbprint -eq $thumbprint } | Remove-Item`);
138
166
  }
167
+ const tracePart = typeof identifier === 'string' ? `'${identifier}'` : JSON.stringify(identifier);
168
+ (0, generalUtils_js_1.logIf)(mergedOptions.logTraceMessages, `uninstalling cert ${tracePart}`);
169
+ const result = await (0, generalUtils_js_1.spawnAsync)('powershell', psCommandArgs, { stdio: mergedOptions.logSpawnOutput ? 'inherit' : 'pipe' });
170
+ throwIfSpawnResultError(result);
171
+ (0, generalUtils_js_1.logIf)(mergedOptions.logSuccess, `${generalUtils_js_1.Emoji.GreenCheck} Successfully uninstalled cert`);
139
172
  }
140
173
  exports.winUninstallCert = winUninstallCert;
174
+ /**
175
+ * Uses Powershell to get info about a cert.
176
+ * @param pfxPath The path to the pfx file to get info for.
177
+ * @returns The subject, thumbprint and pfxPath of the cert.
178
+ */
179
+ async function winGetPfxInfo(pfxPath) {
180
+ if (!(0, generalUtils_js_1.isPlatformWindows)()) {
181
+ throw new Error('winGetPfxInfo is only supported on Windows');
182
+ }
183
+ validatePfxPath(pfxPath);
184
+ const psCommandArgs = (0, generalUtils_js_1.getPowershellHackArgs)(`Get-PfxCertificate -FilePath '${pfxPath}' | Select-Object -Property Subject, Thumbprint, @{Name='PfxPath';Expression={'${pfxPath}'}} | ConvertTo-Json`);
185
+ const result = await (0, generalUtils_js_1.spawnAsync)('powershell', psCommandArgs, { stdio: 'pipe' });
186
+ throwIfSpawnResultError(result);
187
+ const json = result.stdout.trim();
188
+ const parsedJson = JSON.parse(json);
189
+ const certInfo = {
190
+ subject: parsedJson.Subject,
191
+ thumbprint: parsedJson.Thumbprint,
192
+ pfxPath: parsedJson.PfxPath
193
+ };
194
+ return certInfo;
195
+ }
196
+ exports.winGetPfxInfo = winGetPfxInfo;
141
197
  /**
142
198
  * Does not actually do anything - just outputs the manual instructions for installing a cert for use by chrome on linux.
143
199
  */
@@ -146,34 +202,13 @@ function linuxInstallCert() {
146
202
  Manual Instructions:
147
203
  - In Chrome, go to chrome://settings/certificates
148
204
  - Select Authorities -> import
149
- - Select your generated .crt file (in the ./cert/ directory by default - if you haven't generated it, see the generateCertWithOpenSsl method)
205
+ - Select your generated .crt file (in the ./cert/ directory by default - if you haven't generated it, see the generateCertWithOpenSsl function)
150
206
  - Check box for "Trust certificate for identifying websites"
151
207
  - Click OK
152
208
  - Reload site`;
153
209
  console.log(instructions);
154
210
  }
155
211
  exports.linuxInstallCert = linuxInstallCert;
156
- /**
157
- * Uses Powershell to check if a cert is already installed to the local machine's trusted root store.
158
- * @param urlOrSubject The url or subject of the cert to check. If the cert was installed with the winInstallCert method, this will be the url passed to that method.
159
- * @returns `true` if the cert is already installed, `false` otherwise.
160
- */
161
- async function winCertAlreadyInstalled(urlOrSubject) {
162
- const psCommand = `${powershellHackPrefix}Get-ChildItem Cert:\\LocalMachine\\Root | Where-Object { $_.Subject -match '${urlOrSubject}' }`;
163
- // The stdio option of 'pipe' is important here - if left to default of spawnAsync ('inherit'), stdout will be empty
164
- const result = await nodeCliUtils.spawnAsync('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', psCommand], { stdio: ['inherit', 'pipe', 'pipe'] });
165
- if (result.code !== 0) {
166
- throw Error(`powershell command to find installed cert failed with exit code ${result.code}`);
167
- }
168
- const lines = nodeCliUtils.stringToNonEmptyLines(result.stdout);
169
- for (const line of lines) {
170
- if (line.includes(urlOrSubject)) {
171
- return true;
172
- }
173
- }
174
- return false;
175
- }
176
- exports.winCertAlreadyInstalled = winCertAlreadyInstalled;
177
212
  function throwIfMaybeBadUrlChars(url, varName = 'url') {
178
213
  if (url.includes(' ')) {
179
214
  throw Error(`${varName} should not contain spaces`);
@@ -186,7 +221,7 @@ function throwIfMaybeBadUrlChars(url, varName = 'url') {
186
221
  }
187
222
  }
188
223
  function getBrewOpensslPath() {
189
- const brewResult = nodeCliUtils.simpleSpawnSync('brew', ['--prefix', 'openssl']);
224
+ const brewResult = (0, generalUtils_js_1.simpleSpawnSync)('brew', ['--prefix', 'openssl']);
190
225
  if (brewResult.error) {
191
226
  throw Error('error attempting to find openssl installed by brew');
192
227
  }
@@ -198,6 +233,36 @@ function getBrewOpensslPath() {
198
233
  function getSanCnfFileContents(url) {
199
234
  return sanCnfTemplate.replace(/{{url}}/g, url);
200
235
  }
236
+ function validateSubject(subject) {
237
+ if (subject.includes('\\') || subject.includes('/') || subject.endsWith('.pfx')) {
238
+ throw new Error(`The subject appears to be a file path, which is not allowed. Did you mean to pass something like this instead: { pfxPath: '${subject}' } ?`);
239
+ }
240
+ validateNoQuotes('subject', subject);
241
+ }
242
+ function validateNoQuotes(name, value) {
243
+ if (value.includes("'") || value.includes('"')) {
244
+ throw new Error(`The value passed for '${name}' contains a single or double quote, which is not allowed.`);
245
+ }
246
+ }
247
+ function throwIfSpawnResultError(result) {
248
+ if (result.code !== 0) {
249
+ // There won't be any stderr if stdio was set to 'inherit', so we're checking first
250
+ if (result.stderr) {
251
+ console.error((0, colors_js_1.red)('Error:'), result.stderr);
252
+ }
253
+ throw Error(`Spawned command failed with exit code ${result.code}`);
254
+ }
255
+ }
256
+ function validatePfxPath(pfxPath) {
257
+ if (!pfxPath.endsWith('.pfx')) {
258
+ throw new Error('pfxPath must end with .pfx');
259
+ }
260
+ (0, generalUtils_js_1.requireValidPath)('pfxPath', pfxPath);
261
+ validateNoQuotes('pfxPath', pfxPath);
262
+ }
263
+ function getRequiresElevatedPermissionsMessage(isInstall = true) {
264
+ return `${generalUtils_js_1.Emoji.Info} Important: ${isInstall ? '' : 'un'}installing a certificate requires elevated permissions`;
265
+ }
201
266
  // Newer cert requirements force the need for "extension info" with DNS and IP info, but openssl v1.x doesn't support that with the
202
267
  // CLI option -addext, so we're using a san.cnf file instead and passing this into the CLI command with the -config option.
203
268
  const sanCnfTemplate = `[req]
@@ -216,4 +281,4 @@ DNS.1 = {{url}}
216
281
  IP.1 = 127.0.0.1
217
282
 
218
283
  `;
219
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydFV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NlcnRVdGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHNEQUF3QjtBQUN4QixnRUFBa0M7QUFDbEMsMERBQTRCO0FBQzVCLGdFQUFpRDtBQUNqRCx1REFBdUM7QUFFdkMsTUFBTSxvQkFBb0IsR0FBRywwQ0FBMEMsQ0FBQTtBQUN2RSxNQUFNLG9CQUFvQixHQUFHLHdGQUF3RixDQUFBO0FBRXJIOzs7O0dBSUc7QUFDSSxLQUFLLFVBQVUsdUJBQXVCLENBQUMsR0FBVyxFQUFFLGtCQUEwQixRQUFRO0lBQzNGLFlBQVksQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFBO0lBQ3RDLHVCQUF1QixDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBQzVCLE1BQU0sS0FBSyxHQUFHLFlBQVksQ0FBQyxhQUFhLEVBQUUsQ0FBQTtJQUMxQyxNQUFNLFNBQVMsR0FBRyxFQUFFLEdBQUcsRUFBRSxlQUFlLEVBQUUsQ0FBQTtJQUUxQyxJQUFBLHFCQUFHLEVBQUMsb0NBQW9DLENBQUMsQ0FBQTtJQUN6QyxJQUFJLGVBQWUsR0FBVyxFQUFFLENBQUE7SUFDaEMsSUFBSSxDQUFDLEtBQUssRUFBRTtRQUNWLE1BQU0sV0FBVyxHQUFHLFlBQVksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsUUFBUSxDQUFBO1FBQzlELElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDaEIsTUFBTSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQTtTQUNyRDtRQUNELElBQUEscUJBQUcsRUFBQyx1QkFBdUIsV0FBVyxFQUFFLENBQUMsQ0FBQTtLQUMxQztTQUFNLElBQUksS0FBSyxFQUFFO1FBQ2hCLE1BQU0sb0JBQW9CLEdBQUcsa0JBQWtCLEVBQUUsQ0FBQTtRQUNqRCxJQUFJLENBQUMsb0JBQW9CLEVBQUU7WUFDekIsTUFB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
284
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydFV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NlcnRVdGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxzREFBd0I7QUFDeEIsZ0VBQWtDO0FBQ2xDLDBEQUE0QjtBQUM1Qix1REFlMEI7QUFDMUIsMkNBQWlDO0FBZWpDLE1BQU0scUJBQXFCLEdBQW1CO0lBQzVDLGNBQWMsRUFBRSxLQUFLO0lBQ3JCLGdCQUFnQixFQUFFLEtBQUs7SUFDdkIsNkJBQTZCLEVBQUUsSUFBSTtJQUNuQyxVQUFVLEVBQUUsSUFBSTtDQUNqQixDQUFBO0FBV0Q7Ozs7O0dBS0c7QUFDSSxLQUFLLFVBQVUsdUJBQXVCLENBQUMsR0FBVyxFQUFFLE9BQXNDO0lBQy9GLElBQUEsK0JBQWEsRUFBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUE7SUFDekIsdUJBQXVCLENBQUMsR0FBRyxDQUFDLENBQUE7SUFDNUIsTUFBTSxLQUFLLEdBQUcsSUFBQSwrQkFBYSxHQUFFLENBQUE7SUFFN0IsTUFBTSxhQUFhLEdBQXdCLEVBQUUsR0FBRyxxQkFBcUIsRUFBRSxlQUFlLEVBQUUsUUFBUSxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUE7SUFFOUcsTUFBTSxTQUFTLEdBQW1DLEVBQUUsR0FBRyxFQUFFLGFBQWEsQ0FBQyxlQUFlLEVBQUUsS0FBSyxFQUFFLGFBQWEsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUE7SUFFbEosSUFBQSx1QkFBSyxFQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsRUFBRSxrQ0FBa0MsQ0FBQyxDQUFBO0lBRXpFLElBQUksZUFBZSxHQUFXLEVBQUUsQ0FBQTtJQUNoQyxJQUFJLENBQUMsS0FBSyxFQUFFO1FBQ1YsTUFBTSxXQUFXLEdBQUcsSUFBQSwyQkFBUyxFQUFDLFNBQVMsQ0FBQyxDQUFDLFFBQVEsQ0FBQTtRQUNqRCxJQUFJLENBQUMsV0FBVyxF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
@@ -0,0 +1,17 @@
1
+ export declare enum AnsiColor {
2
+ RESET = "\u001B[0m",
3
+ RED = "\u001B[31m",
4
+ GREEN = "\u001B[32m",
5
+ YELLOW = "\u001B[33m",
6
+ CYAN = "\u001B[96m",
7
+ GRAY = "\u001B[90m",
8
+ PURPLE = "\u001B[35m"
9
+ }
10
+ export declare const color: (str: string, colorAnsiCode: AnsiColor) => string;
11
+ export declare const red: (str: string) => string;
12
+ export declare const green: (str: string) => string;
13
+ export declare const cyan: (str: string) => string;
14
+ export declare const gray: (str: string) => string;
15
+ export declare const purple: (str: string) => string;
16
+ export declare const yellow: (str: string) => string;
17
+ //# sourceMappingURL=colors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/colors.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,KAAK,cAAY;IACjB,GAAG,eAAa;IAChB,KAAK,eAAa;IAClB,MAAM,eAAa;IACnB,IAAI,eAAa;IACjB,IAAI,eAAa;IACjB,MAAM,eAAa;CACpB;AAED,eAAO,MAAM,KAAK,QAAS,MAAM,iBAAiB,SAAS,KAAG,MAE7D,CAAA;AAED,eAAO,MAAM,GAAG,QAAS,MAAM,WAA8B,CAAA;AAC7D,eAAO,MAAM,KAAK,QAAS,MAAM,WAAgC,CAAA;AACjE,eAAO,MAAM,IAAI,QAAS,MAAM,WAA+B,CAAA;AAC/D,eAAO,MAAM,IAAI,QAAS,MAAM,WAA+B,CAAA;AAC/D,eAAO,MAAM,MAAM,QAAS,MAAM,WAAiC,CAAA;AACnE,eAAO,MAAM,MAAM,QAAS,MAAM,WAAiC,CAAA"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.yellow = exports.purple = exports.gray = exports.cyan = exports.green = exports.red = exports.color = exports.AnsiColor = void 0;
4
+ var AnsiColor;
5
+ (function (AnsiColor) {
6
+ AnsiColor["RESET"] = "\u001B[0m";
7
+ AnsiColor["RED"] = "\u001B[31m";
8
+ AnsiColor["GREEN"] = "\u001B[32m";
9
+ AnsiColor["YELLOW"] = "\u001B[33m";
10
+ AnsiColor["CYAN"] = "\u001B[96m";
11
+ AnsiColor["GRAY"] = "\u001B[90m";
12
+ AnsiColor["PURPLE"] = "\u001B[35m";
13
+ })(AnsiColor || (exports.AnsiColor = AnsiColor = {}));
14
+ const color = (str, colorAnsiCode) => {
15
+ return `${colorAnsiCode}${str}${AnsiColor.RESET}`;
16
+ };
17
+ exports.color = color;
18
+ const red = (str) => (0, exports.color)(str, AnsiColor.RED);
19
+ exports.red = red;
20
+ const green = (str) => (0, exports.color)(str, AnsiColor.GREEN);
21
+ exports.green = green;
22
+ const cyan = (str) => (0, exports.color)(str, AnsiColor.CYAN);
23
+ exports.cyan = cyan;
24
+ const gray = (str) => (0, exports.color)(str, AnsiColor.GRAY);
25
+ exports.gray = gray;
26
+ const purple = (str) => (0, exports.color)(str, AnsiColor.PURPLE);
27
+ exports.purple = purple;
28
+ const yellow = (str) => (0, exports.color)(str, AnsiColor.YELLOW);
29
+ exports.yellow = yellow;
30
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbG9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxJQUFZLFNBUVg7QUFSRCxXQUFZLFNBQVM7SUFDbkIsZ0NBQWlCLENBQUE7SUFDakIsK0JBQWdCLENBQUE7SUFDaEIsaUNBQWtCLENBQUE7SUFDbEIsa0NBQW1CLENBQUE7SUFDbkIsZ0NBQWlCLENBQUE7SUFDakIsZ0NBQWlCLENBQUE7SUFDakIsa0NBQW1CLENBQUE7QUFDckIsQ0FBQyxFQVJXLFNBQVMseUJBQVQsU0FBUyxRQVFwQjtBQUVNLE1BQU0sS0FBSyxHQUFHLENBQUMsR0FBVyxFQUFFLGFBQXdCLEVBQVUsRUFBRTtJQUNyRSxPQUFPLEdBQUcsYUFBYSxHQUFHLEdBQUcsR0FBRyxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUE7QUFDbkQsQ0FBQyxDQUFBO0FBRlksUUFBQSxLQUFLLFNBRWpCO0FBRU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxHQUFXLEVBQUUsRUFBRSxDQUFDLElBQUEsYUFBSyxFQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUE7QUFBaEQsUUFBQSxHQUFHLE9BQTZDO0FBQ3RELE1BQU0sS0FBSyxHQUFHLENBQUMsR0FBVyxFQUFFLEVBQUUsQ0FBQyxJQUFBLGFBQUssRUFBQyxHQUFHLEVBQUUsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBQXBELFFBQUEsS0FBSyxTQUErQztBQUMxRCxNQUFNLElBQUksR0FBRyxDQUFDLEdBQVcsRUFBRSxFQUFFLENBQUMsSUFBQSxhQUFLLEVBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtBQUFsRCxRQUFBLElBQUksUUFBOEM7QUFDeEQsTUFBTSxJQUFJLEdBQUcsQ0FBQyxHQUFXLEVBQUUsRUFBRSxDQUFDLElBQUEsYUFBSyxFQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUE7QUFBbEQsUUFBQSxJQUFJLFFBQThDO0FBQ3hELE1BQU0sTUFBTSxHQUFHLENBQUMsR0FBVyxFQUFFLEVBQUUsQ0FBQyxJQUFBLGFBQUssRUFBQyxHQUFHLEVBQUUsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0FBQXRELFFBQUEsTUFBTSxVQUFnRDtBQUM1RCxNQUFNLE1BQU0sR0FBRyxDQUFDLEdBQVcsRUFBRSxFQUFFLENBQUMsSUFBQSxhQUFLLEVBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQTtBQUF0RCxRQUFBLE1BQU0sVUFBZ0QifQ==