@heroku/heroku-cli-util 10.4.0-beta.0 → 10.4.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ import PsqlService from './utils/pg/psql.js';
11
11
  import { ago } from './ux/ago.js';
12
12
  import { alignColumns } from './ux/align-columns.js';
13
13
  import { anykey } from './ux/any-key.js';
14
+ import { confirmCommand } from './ux/confirm-command.js';
14
15
  import { toHumanReadableDataSize } from './ux/data-size.js';
15
16
  import { formatPrice } from './ux/format-price.js';
16
17
  import { openUrl } from './ux/open-url.js';
@@ -58,6 +59,7 @@ export declare const hux: {
58
59
  alignColumns: typeof alignColumns;
59
60
  anykey: typeof anykey;
60
61
  confirm: (message: string, { defaultAnswer, ms, }?: import("./ux/confirm.js").PromptInputs<boolean>) => Promise<boolean>;
62
+ confirmCommand: typeof confirmCommand;
61
63
  formatPrice: typeof formatPrice;
62
64
  openUrl: typeof openUrl;
63
65
  prompt: typeof prompt;
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ import { ago } from './ux/ago.js';
11
11
  import { alignColumns } from './ux/align-columns.js';
12
12
  import { anykey } from './ux/any-key.js';
13
13
  import { confirm } from './ux/confirm.js';
14
+ import { confirmCommand } from './ux/confirm-command.js';
14
15
  import { toHumanReadableDataSize } from './ux/data-size.js';
15
16
  import { formatPrice } from './ux/format-price.js';
16
17
  import { openUrl } from './ux/open-url.js';
@@ -50,6 +51,7 @@ export const hux = {
50
51
  alignColumns,
51
52
  anykey,
52
53
  confirm,
54
+ confirmCommand,
53
55
  formatPrice,
54
56
  openUrl,
55
57
  prompt,
@@ -0,0 +1,38 @@
1
+ import { prompt } from './prompt.js';
2
+ type ConfirmCommandOptions = {
3
+ abortedMessage?: string;
4
+ comparison: string;
5
+ confirmation?: string;
6
+ promptFunction?: typeof prompt;
7
+ warningMessage?: string;
8
+ };
9
+ /**
10
+ * @description Prompts the user to confirm a destructive action by typing a comparison string, or validates a
11
+ * pre-provided confirmation.
12
+ * @param options - Configuration options for the confirmation command.
13
+ * @param options.abortedMessage - Custom message to display when the action is aborted (default: 'Aborted.').
14
+ * @param options.comparison - The string that must be entered to confirm the action (required). Typically the app name,
15
+ * but can be other identifiers like a Private Space name.
16
+ * @param options.confirmation - Pre-provided confirmation string to validate without prompting (optional). If provided
17
+ * and matches comparison, returns immediately without prompting.
18
+ * @param options.promptFunction - Function to use for prompting (default: prompt, used for dependency injection in tests).
19
+ * @param options.warningMessage - Custom warning message to display before prompting (optional). Default message assumes
20
+ * comparison is an app name. Provide a custom message if using a different identifier.
21
+ * @returns Promise that resolves if confirmation matches, or throws an error if it doesn't.
22
+ * @throws {Error} When confirmation doesn't match the comparison string.
23
+ * @example
24
+ * // Interactive prompt
25
+ * await confirmCommand({comparison: 'my-app'})
26
+ *
27
+ * // Pre-provided confirmation (no prompt)
28
+ * await confirmCommand({comparison: 'my-app', confirmation: 'my-app'})
29
+ *
30
+ * // Custom messages
31
+ * await confirmCommand({
32
+ * comparison: 'my-app',
33
+ * warningMessage: 'This will delete your database',
34
+ * abortedMessage: 'Database deletion cancelled.'
35
+ * })
36
+ */
37
+ export declare function confirmCommand({ abortedMessage, comparison, confirmation, promptFunction, warningMessage, }: ConfirmCommandOptions): Promise<void>;
38
+ export {};
@@ -0,0 +1,56 @@
1
+ import { ux } from '@oclif/core';
2
+ import tsheredoc from 'tsheredoc';
3
+ import * as color from './colors.js';
4
+ import { prompt } from './prompt.js';
5
+ /**
6
+ * @description Prompts the user to confirm a destructive action by typing a comparison string, or validates a
7
+ * pre-provided confirmation.
8
+ * @param options - Configuration options for the confirmation command.
9
+ * @param options.abortedMessage - Custom message to display when the action is aborted (default: 'Aborted.').
10
+ * @param options.comparison - The string that must be entered to confirm the action (required). Typically the app name,
11
+ * but can be other identifiers like a Private Space name.
12
+ * @param options.confirmation - Pre-provided confirmation string to validate without prompting (optional). If provided
13
+ * and matches comparison, returns immediately without prompting.
14
+ * @param options.promptFunction - Function to use for prompting (default: prompt, used for dependency injection in tests).
15
+ * @param options.warningMessage - Custom warning message to display before prompting (optional). Default message assumes
16
+ * comparison is an app name. Provide a custom message if using a different identifier.
17
+ * @returns Promise that resolves if confirmation matches, or throws an error if it doesn't.
18
+ * @throws {Error} When confirmation doesn't match the comparison string.
19
+ * @example
20
+ * // Interactive prompt
21
+ * await confirmCommand({comparison: 'my-app'})
22
+ *
23
+ * // Pre-provided confirmation (no prompt)
24
+ * await confirmCommand({comparison: 'my-app', confirmation: 'my-app'})
25
+ *
26
+ * // Custom messages
27
+ * await confirmCommand({
28
+ * comparison: 'my-app',
29
+ * warningMessage: 'This will delete your database',
30
+ * abortedMessage: 'Database deletion cancelled.'
31
+ * })
32
+ */
33
+ export async function confirmCommand({ abortedMessage, comparison, confirmation, promptFunction = prompt, warningMessage, }) {
34
+ const heredoc = tsheredoc.default;
35
+ if (!abortedMessage) {
36
+ abortedMessage = 'Aborted.';
37
+ }
38
+ if (confirmation) {
39
+ if (confirmation === comparison)
40
+ return;
41
+ throw new Error(`Confirmation ${color.bold.red(confirmation)} did not match ${color.bold.red(comparison)}. ${abortedMessage}`);
42
+ }
43
+ if (!warningMessage) {
44
+ warningMessage = heredoc `
45
+ Destructive Action
46
+ This command will affect the app ${color.bold.red(comparison)}
47
+ `;
48
+ }
49
+ ux.warn(warningMessage);
50
+ process.stderr.write('\n');
51
+ const entered = await promptFunction(`To proceed, type ${color.bold.red(comparison)} or re-run this command with ${color.bold.red(`--confirm ${comparison}`)}`, { required: true });
52
+ if (entered === comparison) {
53
+ return;
54
+ }
55
+ throw new Error(`Confirmation did not match ${color.bold.red(comparison)}. ${abortedMessage}`);
56
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@heroku/heroku-cli-util",
4
- "version": "10.4.0-beta.0",
4
+ "version": "10.4.0-beta.1",
5
5
  "description": "Set of helpful CLI utilities",
6
6
  "author": "Heroku",
7
7
  "license": "ISC",
@@ -38,13 +38,11 @@
38
38
  "mock-stdin": "^1.0.0",
39
39
  "nock": "^13.2.9",
40
40
  "open": "^11",
41
- "printf": "^0.6.1",
42
41
  "sinon": "^18.0.1",
43
42
  "sinon-chai": "^3.7.0",
44
43
  "tmp": "^0.2.5",
45
44
  "ts-node": "^10.9.2",
46
45
  "tsconfig-paths": "^4.2.0",
47
- "tsheredoc": "^1.0.1",
48
46
  "typescript": "^5.4.0"
49
47
  },
50
48
  "dependencies": {
@@ -55,6 +53,8 @@
55
53
  "ansis": "^4.1.0",
56
54
  "debug": "^4.4.0",
57
55
  "inquirer": "^12.6.1",
56
+ "printf": "^0.6.1",
57
+ "tsheredoc": "^1.0.1",
58
58
  "tunnel-ssh": "5.2.0"
59
59
  },
60
60
  "engines": {