heroku 11.2.0 → 11.3.0

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 (184) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/bin/run.js +8 -3
  3. package/dist/commands/access/add.js +1 -1
  4. package/dist/commands/access/index.js +1 -1
  5. package/dist/commands/access/update.js +2 -2
  6. package/dist/commands/addons/create.js +1 -1
  7. package/dist/commands/addons/destroy.js +3 -3
  8. package/dist/commands/addons/docs.js +1 -1
  9. package/dist/commands/addons/index.js +4 -4
  10. package/dist/commands/addons/info.js +1 -1
  11. package/dist/commands/addons/plans.d.ts +5 -5
  12. package/dist/commands/addons/plans.js +12 -10
  13. package/dist/commands/addons/wait.js +1 -1
  14. package/dist/commands/apps/create.js +1 -1
  15. package/dist/commands/apps/destroy.js +1 -1
  16. package/dist/commands/apps/diff.js +14 -14
  17. package/dist/commands/apps/errors.js +8 -8
  18. package/dist/commands/apps/info.js +3 -3
  19. package/dist/commands/apps/transfer.js +2 -2
  20. package/dist/commands/certs/add.d.ts +1 -1
  21. package/dist/commands/certs/add.js +2 -2
  22. package/dist/commands/certs/auto/disable.js +1 -1
  23. package/dist/commands/certs/auto/index.js +1 -1
  24. package/dist/commands/certs/index.js +1 -1
  25. package/dist/commands/certs/info.js +1 -1
  26. package/dist/commands/certs/remove.js +1 -1
  27. package/dist/commands/certs/update.js +3 -3
  28. package/dist/commands/container/login.d.ts +1 -1
  29. package/dist/commands/container/login.js +1 -1
  30. package/dist/commands/container/logout.d.ts +1 -1
  31. package/dist/commands/container/logout.js +1 -1
  32. package/dist/commands/container/pull.d.ts +1 -1
  33. package/dist/commands/container/pull.js +1 -1
  34. package/dist/commands/container/push.d.ts +1 -1
  35. package/dist/commands/container/push.js +1 -1
  36. package/dist/commands/container/run.d.ts +1 -1
  37. package/dist/commands/container/run.js +1 -1
  38. package/dist/commands/data/maintenances/history.d.ts +1 -1
  39. package/dist/commands/data/maintenances/history.js +2 -2
  40. package/dist/commands/data/maintenances/index.d.ts +1 -1
  41. package/dist/commands/data/maintenances/index.js +2 -2
  42. package/dist/commands/data/maintenances/info.d.ts +1 -1
  43. package/dist/commands/data/maintenances/info.js +1 -1
  44. package/dist/commands/data/maintenances/run.d.ts +1 -1
  45. package/dist/commands/data/maintenances/run.js +1 -1
  46. package/dist/commands/data/maintenances/schedule.d.ts +1 -1
  47. package/dist/commands/data/maintenances/schedule.js +1 -1
  48. package/dist/commands/data/maintenances/wait.d.ts +1 -1
  49. package/dist/commands/data/maintenances/wait.js +1 -1
  50. package/dist/commands/data/maintenances/window/index.d.ts +1 -1
  51. package/dist/commands/data/maintenances/window/index.js +1 -1
  52. package/dist/commands/data/maintenances/window/update.d.ts +1 -1
  53. package/dist/commands/data/maintenances/window/update.js +1 -1
  54. package/dist/commands/data/pg/attachments/create.d.ts +1 -1
  55. package/dist/commands/data/pg/attachments/create.js +1 -1
  56. package/dist/commands/data/pg/attachments/destroy.d.ts +1 -1
  57. package/dist/commands/data/pg/attachments/destroy.js +1 -1
  58. package/dist/commands/data/pg/attachments/index.d.ts +1 -1
  59. package/dist/commands/data/pg/attachments/index.js +1 -1
  60. package/dist/commands/data/pg/create.d.ts +1 -1
  61. package/dist/commands/data/pg/create.js +5 -5
  62. package/dist/commands/data/pg/credentials/create.d.ts +1 -1
  63. package/dist/commands/data/pg/credentials/create.js +1 -1
  64. package/dist/commands/data/pg/credentials/destroy.d.ts +1 -1
  65. package/dist/commands/data/pg/credentials/destroy.js +1 -1
  66. package/dist/commands/data/pg/credentials/index.d.ts +1 -1
  67. package/dist/commands/data/pg/credentials/index.js +3 -3
  68. package/dist/commands/data/pg/credentials/rotate.d.ts +1 -1
  69. package/dist/commands/data/pg/credentials/rotate.js +1 -1
  70. package/dist/commands/data/pg/credentials/url.d.ts +1 -1
  71. package/dist/commands/data/pg/credentials/url.js +1 -1
  72. package/dist/commands/data/pg/destroy.d.ts +1 -1
  73. package/dist/commands/data/pg/destroy.js +2 -2
  74. package/dist/commands/data/pg/docs.d.ts +1 -1
  75. package/dist/commands/data/pg/docs.js +1 -1
  76. package/dist/commands/data/pg/fork.d.ts +1 -1
  77. package/dist/commands/data/pg/fork.js +3 -3
  78. package/dist/commands/data/pg/info.d.ts +1 -1
  79. package/dist/commands/data/pg/info.js +2 -2
  80. package/dist/commands/data/pg/levels.d.ts +1 -1
  81. package/dist/commands/data/pg/levels.js +1 -1
  82. package/dist/commands/data/pg/quotas/index.d.ts +1 -1
  83. package/dist/commands/data/pg/quotas/index.js +2 -2
  84. package/dist/commands/data/pg/quotas/update.d.ts +1 -1
  85. package/dist/commands/data/pg/quotas/update.js +2 -2
  86. package/dist/commands/data/pg/settings.d.ts +1 -1
  87. package/dist/commands/data/pg/settings.js +1 -1
  88. package/dist/commands/data/pg/update.d.ts +1 -1
  89. package/dist/commands/data/pg/update.js +3 -3
  90. package/dist/commands/data/pg/upgrade/run.d.ts +15 -0
  91. package/dist/commands/data/pg/upgrade/run.js +58 -0
  92. package/dist/commands/data/pg/upgrade/wait.d.ts +6 -0
  93. package/dist/commands/data/pg/upgrade/wait.js +18 -0
  94. package/dist/commands/data/pg/wait.d.ts +2 -1
  95. package/dist/commands/data/pg/wait.js +8 -6
  96. package/dist/commands/domains/index.js +2 -2
  97. package/dist/commands/pg/backups/delete.js +1 -1
  98. package/dist/commands/pg/backups/restore.js +1 -1
  99. package/dist/commands/pg/copy.js +1 -1
  100. package/dist/commands/pg/credentials/destroy.js +1 -1
  101. package/dist/commands/pg/credentials/repair-default.js +1 -1
  102. package/dist/commands/pg/credentials/rotate.js +1 -1
  103. package/dist/commands/pg/credentials.js +1 -1
  104. package/dist/commands/pg/links/destroy.js +1 -1
  105. package/dist/commands/pg/pull.js +1 -1
  106. package/dist/commands/pg/push.js +1 -1
  107. package/dist/commands/pg/reset.js +1 -1
  108. package/dist/commands/pg/unfollow.js +1 -1
  109. package/dist/commands/pg/upgrade/cancel.js +1 -1
  110. package/dist/commands/pg/upgrade/dryrun.js +1 -1
  111. package/dist/commands/pg/upgrade/prepare.js +1 -1
  112. package/dist/commands/pg/upgrade/run.js +1 -1
  113. package/dist/commands/ps/index.js +1 -1
  114. package/dist/commands/redis/cli.js +1 -1
  115. package/dist/commands/redis/stats-reset.js +1 -1
  116. package/dist/commands/redis/upgrade.js +1 -1
  117. package/dist/commands/releases/index.js +1 -1
  118. package/dist/commands/releases/info.js +1 -1
  119. package/dist/commands/spaces/destroy.js +1 -1
  120. package/dist/commands/spaces/peerings/destroy.js +1 -1
  121. package/dist/commands/spaces/vpn/destroy.js +1 -1
  122. package/dist/hooks/command_not_found/setup-otel-telemetry.js +4 -1
  123. package/dist/hooks/finally/send-otel-and-sentry-errors.js +4 -1
  124. package/dist/hooks/init/setup-otel-telemetry.js +4 -1
  125. package/dist/hooks/postrun/send-otel-telemetry.js +6 -1
  126. package/dist/hooks/prerun/collect-and-send-herokulytics.js +4 -1
  127. package/dist/lib/addons/{create_addon.js → create-addon.js} +1 -1
  128. package/dist/lib/addons/{destroy_addon.js → destroy-addon.js} +1 -1
  129. package/dist/lib/addons/util.js +1 -1
  130. package/dist/lib/analytics-telemetry/telemetry-manager.js +0 -1
  131. package/dist/lib/analytics-telemetry/telemetry-utils.d.ts +6 -0
  132. package/dist/lib/analytics-telemetry/telemetry-utils.js +22 -3
  133. package/dist/lib/analytics-telemetry/worker-client.d.ts +5 -3
  134. package/dist/lib/analytics-telemetry/worker-client.js +20 -6
  135. package/dist/lib/certs/{certificate_details.d.ts → certificate-details.d.ts} +1 -1
  136. package/dist/lib/certs/{certificate_details.js → certificate-details.js} +1 -1
  137. package/dist/lib/certs/{display_table.d.ts → display-table.d.ts} +1 -1
  138. package/dist/lib/certs/{display_table.js → display-table.js} +1 -1
  139. package/dist/lib/certs/flags.d.ts +1 -1
  140. package/dist/lib/data/types.d.ts +156 -153
  141. package/dist/lib/data/types.js +3 -3
  142. package/dist/lib/utils/{tableUtils.js → table-utils.js} +1 -1
  143. package/npm-shrinkwrap.json +27 -323
  144. package/oclif.manifest.json +2099 -1964
  145. package/package.json +2 -3
  146. /package/dist/lib/addons/{addons_wait.d.ts → addons-wait.d.ts} +0 -0
  147. /package/dist/lib/addons/{addons_wait.js → addons-wait.js} +0 -0
  148. /package/dist/lib/addons/{create_addon.d.ts → create-addon.d.ts} +0 -0
  149. /package/dist/lib/addons/{destroy_addon.d.ts → destroy-addon.d.ts} +0 -0
  150. /package/dist/lib/apps/{error_info.d.ts → error-info.d.ts} +0 -0
  151. /package/dist/lib/apps/{error_info.js → error-info.js} +0 -0
  152. /package/dist/lib/certs/{format_date.d.ts → format-date.d.ts} +0 -0
  153. /package/dist/lib/certs/{format_date.js → format-date.js} +0 -0
  154. /package/dist/lib/certs/{get_cert_and_key.d.ts → get-cert-and-key.d.ts} +0 -0
  155. /package/dist/lib/certs/{get_cert_and_key.js → get-cert-and-key.js} +0 -0
  156. /package/dist/lib/{confirmCommand.d.ts → confirm-command.d.ts} +0 -0
  157. /package/dist/lib/{confirmCommand.js → confirm-command.js} +0 -0
  158. /package/dist/lib/container/{docker_helper.d.ts → docker-helper.d.ts} +0 -0
  159. /package/dist/lib/container/{docker_helper.js → docker-helper.js} +0 -0
  160. /package/dist/lib/data/{baseCommand.d.ts → base-command.d.ts} +0 -0
  161. /package/dist/lib/data/{baseCommand.js → base-command.js} +0 -0
  162. /package/dist/lib/data/{createPool.d.ts → create-pool.d.ts} +0 -0
  163. /package/dist/lib/data/{createPool.js → create-pool.js} +0 -0
  164. /package/dist/lib/data/{credentialUtils.d.ts → credential-utils.d.ts} +0 -0
  165. /package/dist/lib/data/{credentialUtils.js → credential-utils.js} +0 -0
  166. /package/dist/lib/data/{displayQuota.d.ts → display-quota.d.ts} +0 -0
  167. /package/dist/lib/data/{displayQuota.js → display-quota.js} +0 -0
  168. /package/dist/lib/data/{parseProvisionOpts.d.ts → parse-provision-opts.d.ts} +0 -0
  169. /package/dist/lib/data/{parseProvisionOpts.js → parse-provision-opts.js} +0 -0
  170. /package/dist/lib/data/{poolConfig.d.ts → pool-config.d.ts} +0 -0
  171. /package/dist/lib/data/{poolConfig.js → pool-config.js} +0 -0
  172. /package/dist/lib/pg/{push_pull.d.ts → push-pull.d.ts} +0 -0
  173. /package/dist/lib/pg/{push_pull.js → push-pull.js} +0 -0
  174. /package/dist/lib/releases/{status_helper.d.ts → status-helper.d.ts} +0 -0
  175. /package/dist/lib/releases/{status_helper.js → status-helper.js} +0 -0
  176. /package/dist/lib/{teamUtils.d.ts → team-utils.d.ts} +0 -0
  177. /package/dist/lib/{teamUtils.js → team-utils.js} +0 -0
  178. /package/dist/lib/types/{app_errors.d.ts → app-errors.d.ts} +0 -0
  179. /package/dist/lib/types/{app_errors.js → app-errors.js} +0 -0
  180. /package/dist/lib/types/{app_process_tier.d.ts → app-process-tier.d.ts} +0 -0
  181. /package/dist/lib/types/{app_process_tier.js → app-process-tier.js} +0 -0
  182. /package/dist/lib/utils/{keyValueParser.d.ts → key-value-parser.d.ts} +0 -0
  183. /package/dist/lib/utils/{keyValueParser.js → key-value-parser.js} +0 -0
  184. /package/dist/lib/utils/{tableUtils.d.ts → table-utils.d.ts} +0 -0
@@ -0,0 +1,18 @@
1
+ import * as color from '@heroku/heroku-cli-util/color';
2
+ import tsheredoc from 'tsheredoc';
3
+ import DataPgWait from '../wait.js';
4
+ const heredoc = tsheredoc.default;
5
+ export default class DataPgUpgradeWait extends DataPgWait {
6
+ static description = 'shows status of an upgrade until it\'s complete';
7
+ static examples = [
8
+ heredoc(`
9
+ # Wait for upgrade to complete
10
+ ${color.code('<%= config.bin %> <%= command.id %> DATABASE --app myapp')}
11
+ `),
12
+ heredoc(`
13
+ # Wait with custom polling interval (to avoid rate limiting)
14
+ ${color.code('<%= config.bin %> <%= command.id %> DATABASE --app myapp --wait-interval 10')}
15
+ `),
16
+ ];
17
+ classicWaitCommand = 'pg:upgrade:wait';
18
+ }
@@ -1,4 +1,4 @@
1
- import BaseCommand from '../../../lib/data/baseCommand.js';
1
+ import BaseCommand from '../../../lib/data/base-command.js';
2
2
  import notify from '../../../lib/notify.js';
3
3
  export default class DataPgWait extends BaseCommand {
4
4
  static args: {
@@ -12,6 +12,7 @@ export default class DataPgWait extends BaseCommand {
12
12
  remote: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
13
  'wait-interval': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
14
14
  };
15
+ protected classicWaitCommand: string;
15
16
  notify(...args: Parameters<typeof notify>): Promise<void>;
16
17
  run(): Promise<void>;
17
18
  wait(ms: number): Promise<void>;
@@ -1,8 +1,9 @@
1
- import { color, utils } from '@heroku/heroku-cli-util';
2
1
  import { flags as Flags } from '@heroku-cli/command';
2
+ import * as color from '@heroku/heroku-cli-util/color';
3
+ import { DatabaseResolver, isAdvancedDatabase } from '@heroku/heroku-cli-util/utils';
3
4
  import { Args, ux } from '@oclif/core';
4
5
  import tsheredoc from 'tsheredoc';
5
- import BaseCommand from '../../../lib/data/baseCommand.js';
6
+ import BaseCommand from '../../../lib/data/base-command.js';
6
7
  import notify from '../../../lib/notify.js';
7
8
  const heredoc = tsheredoc.default;
8
9
  export default class DataPgWait extends BaseCommand {
@@ -16,7 +17,7 @@ export default class DataPgWait extends BaseCommand {
16
17
  static examples = [
17
18
  heredoc(`
18
19
  # Wait for database to be available
19
- ${color.command('heroku data:pg:wait DATABASE --app myapp')}
20
+ ${color.code('<%= config.bin %> <%= command.id %> DATABASE --app myapp')}
20
21
  `),
21
22
  ];
22
23
  static flags = {
@@ -31,6 +32,7 @@ export default class DataPgWait extends BaseCommand {
31
32
  min: 1,
32
33
  }),
33
34
  };
35
+ classicWaitCommand = 'pg:wait';
34
36
  async notify(...args) {
35
37
  return notify(...args);
36
38
  }
@@ -38,13 +40,13 @@ export default class DataPgWait extends BaseCommand {
38
40
  const { args, flags } = await this.parse(DataPgWait);
39
41
  const { database } = args;
40
42
  const { app, 'no-notify': noNotify, 'wait-interval': waitInterval } = flags;
41
- const databaseResolver = new utils.pg.DatabaseResolver(this.heroku);
43
+ const databaseResolver = new DatabaseResolver(this.heroku);
42
44
  const db = await databaseResolver.getAttachment(app, database);
43
45
  const { addon } = db;
44
- if (!utils.pg.isAdvancedDatabase(addon)) {
46
+ if (!isAdvancedDatabase(addon)) {
45
47
  ux.error(heredoc `
46
48
  You can only use this command on Advanced-tier databases.
47
- Run ${color.code(`heroku pg:wait ${addon.name} -a ${app}`)} instead.`);
49
+ Use ${color.code(`heroku ${this.classicWaitCommand} ${addon.name} -a ${app}`)} instead.`);
48
50
  }
49
51
  await this.waitFor(addon, waitInterval || 5, noNotify);
50
52
  }
@@ -3,9 +3,9 @@ import { color, hux } from '@heroku/heroku-cli-util';
3
3
  import { ux } from '@oclif/core/ux';
4
4
  import { orderBy } from 'natural-orderby';
5
5
  import Uri from 'urijs';
6
- import parseKeyValue from '../../lib/utils/keyValueParser.js';
6
+ import parseKeyValue from '../../lib/utils/key-value-parser.js';
7
7
  import { paginateRequest } from '../../lib/utils/paginator.js';
8
- import { huxTableNoWrapOptions } from '../../lib/utils/tableUtils.js';
8
+ import { huxTableNoWrapOptions } from '../../lib/utils/table-utils.js';
9
9
  export default class DomainsIndex extends Command {
10
10
  static description = 'list domains for an app';
11
11
  static examples = [`${color.command('heroku domains')}
@@ -1,7 +1,7 @@
1
1
  import { color, utils } from '@heroku/heroku-cli-util';
2
2
  import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args, ux } from '@oclif/core';
4
- import ConfirmCommand from '../../../lib/confirmCommand.js';
4
+ import ConfirmCommand from '../../../lib/confirm-command.js';
5
5
  import backupsFactory from '../../../lib/pg/backups.js';
6
6
  export default class Delete extends Command {
7
7
  static args = {
@@ -2,7 +2,7 @@ import { Command, flags } from '@heroku-cli/command';
2
2
  import { color, utils } from '@heroku/heroku-cli-util';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../../lib/confirm-command.js';
6
6
  import backupsFactory from '../../../lib/pg/backups.js';
7
7
  import { nls } from '../../../nls.js';
8
8
  const heredoc = tsheredoc.default;
@@ -1,7 +1,7 @@
1
1
  import { color, utils } from '@heroku/heroku-cli-util';
2
2
  import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args, ux } from '@oclif/core';
4
- import ConfirmCommand from '../../lib/confirmCommand.js';
4
+ import ConfirmCommand from '../../lib/confirm-command.js';
5
5
  import backupsFactory from '../../lib/pg/backups.js';
6
6
  const getAttachmentInfo = async function (heroku, db, app) {
7
7
  const dbResolver = new utils.pg.DatabaseResolver(heroku);
@@ -1,7 +1,7 @@
1
1
  import { Command, flags } from '@heroku-cli/command';
2
2
  import { color, utils } from '@heroku/heroku-cli-util';
3
3
  import { Args, ux } from '@oclif/core';
4
- import ConfirmCommand from '../../../lib/confirmCommand.js';
4
+ import ConfirmCommand from '../../../lib/confirm-command.js';
5
5
  import { essentialPlan } from '../../../lib/pg/util.js';
6
6
  import { nls } from '../../../nls.js';
7
7
  export default class Destroy extends Command {
@@ -2,7 +2,7 @@ import { color, utils } from '@heroku/heroku-cli-util';
2
2
  import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../../lib/confirm-command.js';
6
6
  import { essentialPlan } from '../../../lib/pg/util.js';
7
7
  import { nls } from '../../../nls.js';
8
8
  const heredoc = tsheredoc.default;
@@ -1,7 +1,7 @@
1
1
  import { Command, flags } from '@heroku-cli/command';
2
2
  import { color, utils } from '@heroku/heroku-cli-util';
3
3
  import { Args, ux } from '@oclif/core';
4
- import ConfirmCommand from '../../../lib/confirmCommand.js';
4
+ import ConfirmCommand from '../../../lib/confirm-command.js';
5
5
  import { nls } from '../../../nls.js';
6
6
  export default class Rotate extends Command {
7
7
  static args = {
@@ -2,7 +2,7 @@ import { hux, utils } from '@heroku/heroku-cli-util';
2
2
  import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args } from '@oclif/core';
4
4
  import { presentCredentialAttachments } from '../../lib/pg/util.js';
5
- import { huxTableNoWrapOptions } from '../../lib/utils/tableUtils.js';
5
+ import { huxTableNoWrapOptions } from '../../lib/utils/table-utils.js';
6
6
  import { nls } from '../../nls.js';
7
7
  export default class Credentials extends Command {
8
8
  static args = {
@@ -2,7 +2,7 @@ import { color, utils } from '@heroku/heroku-cli-util';
2
2
  import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../../lib/confirm-command.js';
6
6
  import { essentialPlan } from '../../../lib/pg/util.js';
7
7
  const heredoc = tsheredoc.default;
8
8
  import { nls } from '../../../nls.js';
@@ -5,7 +5,7 @@ import { color, utils } from '@heroku/heroku-cli-util';
5
5
  // import {SpawnOptions, spawn} from 'node:child_process'
6
6
  import childProcess from 'node:child_process';
7
7
  import { nls } from '../../nls.js';
8
- import { connArgs, maybeTunnel, parseExclusions, prepare, spawnPipe, verifyExtensionsMatch, } from '../../lib/pg/push_pull.js';
8
+ import { connArgs, maybeTunnel, parseExclusions, prepare, spawnPipe, verifyExtensionsMatch, } from '../../lib/pg/push-pull.js';
9
9
  const { env } = process;
10
10
  const heredoc = tsheredoc.default;
11
11
  export default class Pull extends Command {
@@ -2,7 +2,7 @@ import { Command, flags } from '@heroku-cli/command';
2
2
  import { Args, ux } from '@oclif/core';
3
3
  import tsheredoc from 'tsheredoc';
4
4
  import { color, utils } from '@heroku/heroku-cli-util';
5
- import { connArgs, maybeTunnel, parseExclusions, prepare, spawnPipe, verifyExtensionsMatch, } from '../../lib/pg/push_pull.js';
5
+ import { connArgs, maybeTunnel, parseExclusions, prepare, spawnPipe, verifyExtensionsMatch, } from '../../lib/pg/push-pull.js';
6
6
  import childProcess from 'node:child_process';
7
7
  import { nls } from '../../nls.js';
8
8
  const heredoc = tsheredoc.default;
@@ -2,7 +2,7 @@ import { color, utils } from '@heroku/heroku-cli-util';
2
2
  import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../lib/confirm-command.js';
6
6
  import { nls } from '../../nls.js';
7
7
  const heredoc = tsheredoc.default;
8
8
  export default class Reset extends Command {
@@ -2,7 +2,7 @@ import { Command, flags } from '@heroku-cli/command';
2
2
  import { Args, ux } from '@oclif/core';
3
3
  import { utils, color } from '@heroku/heroku-cli-util';
4
4
  import { databaseNameFromUrl } from '../../lib/pg/util.js';
5
- import ConfirmCommand from '../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../lib/confirm-command.js';
6
6
  import tsheredoc from 'tsheredoc';
7
7
  import { nls } from '../../nls.js';
8
8
  const heredoc = tsheredoc.default;
@@ -2,7 +2,7 @@ import { color, utils } from '@heroku/heroku-cli-util';
2
2
  import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../../lib/confirm-command.js';
6
6
  import { formatResponseWithCommands } from '../../../lib/pg/util.js';
7
7
  import { nls } from '../../../nls.js';
8
8
  const heredoc = tsheredoc.default;
@@ -2,7 +2,7 @@ import { color, utils } from '@heroku/heroku-cli-util';
2
2
  import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../../lib/confirm-command.js';
6
6
  import { formatResponseWithCommands } from '../../../lib/pg/util.js';
7
7
  import { nls } from '../../../nls.js';
8
8
  const heredoc = tsheredoc.default;
@@ -2,7 +2,7 @@ import { color, utils } from '@heroku/heroku-cli-util';
2
2
  import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../../lib/confirm-command.js';
6
6
  import { formatResponseWithCommands } from '../../../lib/pg/util.js';
7
7
  import { nls } from '../../../nls.js';
8
8
  const heredoc = tsheredoc.default;
@@ -2,7 +2,7 @@ import { color, utils } from '@heroku/heroku-cli-util';
2
2
  import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../../lib/confirm-command.js';
6
6
  import { databaseNameFromUrl, formatResponseWithCommands } from '../../../lib/pg/util.js';
7
7
  import { nls } from '../../../nls.js';
8
8
  const heredoc = tsheredoc.default;
@@ -3,7 +3,7 @@ import { color, hux } from '@heroku/heroku-cli-util';
3
3
  import { ux } from '@oclif/core/ux';
4
4
  import tsheredoc from 'tsheredoc';
5
5
  import { ago } from '../../lib/time.js';
6
- import { huxTableNoWrapOptions } from '../../lib/utils/tableUtils.js';
6
+ import { huxTableNoWrapOptions } from '../../lib/utils/table-utils.js';
7
7
  const heredoc = tsheredoc.default;
8
8
  export default class Index extends Command {
9
9
  static description = 'list dynos for an app';
@@ -7,7 +7,7 @@ import * as readline from 'readline';
7
7
  import Parser from 'redis-parser';
8
8
  import { Client } from 'ssh2';
9
9
  import * as tls from 'tls';
10
- import ConfirmCommand from '../../lib/confirmCommand.js';
10
+ import ConfirmCommand from '../../lib/confirm-command.js';
11
11
  import apiFactory from '../../lib/redis/api.js';
12
12
  const REPLY_OK = 'OK';
13
13
  async function redisCLI(uri, client) {
@@ -2,7 +2,7 @@ import { Command, flags } from '@heroku-cli/command';
2
2
  import * as color from '@heroku/heroku-cli-util/color';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../lib/confirm-command.js';
6
6
  import redisApi from '../../lib/redis/api.js';
7
7
  const heredoc = tsheredoc.default;
8
8
  export default class StatsReset extends Command {
@@ -2,7 +2,7 @@ import { Command, flags } from '@heroku-cli/command';
2
2
  import * as color from '@heroku/heroku-cli-util/color';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../lib/confirm-command.js';
6
6
  import redisApi from '../../lib/redis/api.js';
7
7
  const heredoc = tsheredoc.default;
8
8
  export default class Upgrade extends Command {
@@ -3,7 +3,7 @@ import { color, hux } from '@heroku/heroku-cli-util';
3
3
  import { ux } from '@oclif/core/ux';
4
4
  import ansis from 'ansis';
5
5
  import { lazyModuleLoader } from '../../lib/lazy-module-loader.js';
6
- import * as statusHelper from '../../lib/releases/status_helper.js';
6
+ import * as statusHelper from '../../lib/releases/status-helper.js';
7
7
  import * as time from '../../lib/time.js';
8
8
  const getDescriptionTruncation = function (releases, columns, optimizeKey) {
9
9
  // width management here is quite opaque.
@@ -3,7 +3,7 @@ import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import { quote } from '../../lib/config/quote.js';
5
5
  import { findByLatestOrId } from '../../lib/releases/releases.js';
6
- import { description, color as getStatusColor } from '../../lib/releases/status_helper.js';
6
+ import { description, color as getStatusColor } from '../../lib/releases/status-helper.js';
7
7
  export default class Info extends Command {
8
8
  static args = {
9
9
  release: Args.string({ description: 'ID of the release. If omitted, we use the last release ID.' }),
@@ -3,7 +3,7 @@ import * as color from '@heroku/heroku-cli-util/color';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
5
  import { getGeneration } from '../../lib/apps/generation.js';
6
- import ConfirmCommand from '../../lib/confirmCommand.js';
6
+ import ConfirmCommand from '../../lib/confirm-command.js';
7
7
  import { displayNat } from '../../lib/spaces/spaces.js';
8
8
  const heredoc = tsheredoc.default;
9
9
  export default class Destroy extends Command {
@@ -2,7 +2,7 @@ import * as color from '@heroku/heroku-cli-util/color';
2
2
  import { Command, flags } from '@heroku-cli/command';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../../lib/confirm-command.js';
6
6
  const heredoc = tsheredoc.default;
7
7
  export default class Destroy extends Command {
8
8
  static args = {
@@ -2,7 +2,7 @@ import { Command, flags } from '@heroku-cli/command';
2
2
  import * as color from '@heroku/heroku-cli-util/color';
3
3
  import { Args, ux } from '@oclif/core';
4
4
  import tsheredoc from 'tsheredoc';
5
- import ConfirmCommand from '../../../lib/confirmCommand.js';
5
+ import ConfirmCommand from '../../../lib/confirm-command.js';
6
6
  const heredoc = tsheredoc.default;
7
7
  export default class Destroy extends Command {
8
8
  static args = {
@@ -1,9 +1,12 @@
1
1
  const performance_analytics = async function () {
2
- const { isTelemetryEnabled } = await import('../../lib/analytics-telemetry/telemetry-utils.js');
2
+ const { isTelemetryEnabled, getTelemetryDisabledReason, telemetryDebug } = await import('../../lib/analytics-telemetry/telemetry-utils.js');
3
3
  // Use the consolidated telemetry check
4
4
  if (!isTelemetryEnabled()) {
5
+ const reason = getTelemetryDisabledReason();
6
+ telemetryDebug('Telemetry disabled (%s): skipping command_not_found hook, not setting up telemetry for invalid command', reason);
5
7
  return;
6
8
  }
9
+ telemetryDebug('Telemetry enabled: command_not_found hook setting up telemetry for invalid command');
7
10
  const { telemetryManager } = await import('../../lib/analytics-telemetry/telemetry-manager.js');
8
11
  const globalAny = global;
9
12
  globalAny.cliTelemetry = telemetryManager.reportCmdNotFound(this.config);
@@ -31,11 +31,14 @@ const finallyHook = async function (options) {
31
31
  if (isUserError(options.error)) {
32
32
  return;
33
33
  }
34
- const { isTelemetryEnabled, spawnTelemetryWorker } = await import('../../lib/analytics-telemetry/telemetry-utils.js');
34
+ const { isTelemetryEnabled, getTelemetryDisabledReason, spawnTelemetryWorker, telemetryDebug } = await import('../../lib/analytics-telemetry/telemetry-utils.js');
35
35
  // Use the consolidated telemetry check
36
36
  if (!isTelemetryEnabled()) {
37
+ const reason = getTelemetryDisabledReason();
38
+ telemetryDebug('Telemetry disabled (%s): skipping finally hook, not sending error: %s', reason, options.error.message);
37
39
  return;
38
40
  }
41
+ telemetryDebug('Telemetry enabled: finally hook spawning worker to send error: %s', options.error.message);
39
42
  // Spawn background process to send error without blocking
40
43
  spawnTelemetryWorker(options.error);
41
44
  };
@@ -1,9 +1,12 @@
1
1
  const performance_analytics = async function (options) {
2
- const { isTelemetryEnabled } = await import('../../lib/analytics-telemetry/telemetry-utils.js');
2
+ const { isTelemetryEnabled, getTelemetryDisabledReason, telemetryDebug } = await import('../../lib/analytics-telemetry/telemetry-utils.js');
3
3
  // Use the consolidated telemetry check
4
4
  if (!isTelemetryEnabled()) {
5
+ const reason = getTelemetryDisabledReason();
6
+ telemetryDebug('Telemetry disabled (%s): skipping init hook, not setting up telemetry object', reason);
5
7
  return;
6
8
  }
9
+ telemetryDebug('Telemetry enabled: init hook setting up telemetry object for command');
7
10
  const { telemetryManager } = await import('../../lib/analytics-telemetry/telemetry-manager.js');
8
11
  const globalAny = global;
9
12
  globalAny.cliTelemetry = telemetryManager.setupTelemetry(this.config, options);
@@ -3,15 +3,20 @@ const performance_analytics = async function () {
3
3
  if (!globalAny.cliTelemetry) {
4
4
  return;
5
5
  }
6
- const { computeDuration, isTelemetryEnabled, spawnTelemetryWorker } = await import('../../lib/analytics-telemetry/telemetry-utils.js');
6
+ const { computeDuration, isTelemetryEnabled, getTelemetryDisabledReason, spawnTelemetryWorker, telemetryDebug } = await import('../../lib/analytics-telemetry/telemetry-utils.js');
7
7
  // Use the consolidated telemetry check
8
8
  if (!isTelemetryEnabled()) {
9
+ const reason = getTelemetryDisabledReason();
10
+ telemetryDebug('Telemetry disabled (%s): skipping postrun hook, not sending telemetry for command: %s', reason, globalAny.cliTelemetry.command);
9
11
  return;
10
12
  }
13
+ telemetryDebug('Telemetry enabled: postrun hook spawning worker to send telemetry for command: %s', globalAny.cliTelemetry.command);
11
14
  const cmdStartTime = globalAny.cliTelemetry.commandRunDuration;
12
15
  globalAny.cliTelemetry.commandRunDuration = computeDuration(cmdStartTime);
13
16
  globalAny.cliTelemetry.lifecycleHookCompletion.postrun = true;
14
17
  // Spawn background process to send telemetry without blocking
15
18
  spawnTelemetryWorker(globalAny.cliTelemetry);
19
+ // Mark telemetry as sent to prevent duplicate sends from beforeExit handler
20
+ globalAny.telemetrySent = true;
16
21
  };
17
22
  export default performance_analytics;
@@ -1,9 +1,12 @@
1
1
  const analytics = async function (options) {
2
- const { isTelemetryEnabled, spawnTelemetryWorker } = await import('../../lib/analytics-telemetry/telemetry-utils.js');
2
+ const { isTelemetryEnabled, getTelemetryDisabledReason, spawnTelemetryWorker, telemetryDebug } = await import('../../lib/analytics-telemetry/telemetry-utils.js');
3
3
  // Use the consolidated telemetry check
4
4
  if (!isTelemetryEnabled()) {
5
+ const reason = getTelemetryDisabledReason();
6
+ telemetryDebug('Telemetry disabled (%s): skipping prerun hook, not sending Herokulytics for command: %s', reason, options.Command.id);
5
7
  return;
6
8
  }
9
+ telemetryDebug('Telemetry enabled: prerun hook spawning worker to send Herokulytics for command: %s', options.Command.id);
7
10
  const { telemetryManager } = await import('../../lib/analytics-telemetry/telemetry-manager.js');
8
11
  const globalAny = global;
9
12
  // Only setup telemetry if not already initialized (avoid overwriting init hook data)
@@ -1,6 +1,6 @@
1
1
  import { color, utils } from '@heroku/heroku-cli-util';
2
2
  import { ux } from '@oclif/core/ux';
3
- import { waitForAddonProvisioning } from './addons_wait.js';
3
+ import { waitForAddonProvisioning } from './addons-wait.js';
4
4
  import * as util from './util.js';
5
5
  function formatConfigVarsMessage(addon) {
6
6
  const configVars = addon.config_vars || [];
@@ -1,6 +1,6 @@
1
1
  import { color, utils } from '@heroku/heroku-cli-util';
2
2
  import { ux } from '@oclif/core/ux';
3
- import { waitForAddonDeprovisioning } from './addons_wait.js';
3
+ import { waitForAddonDeprovisioning } from './addons-wait.js';
4
4
  export default async function (heroku, addon, force = false, wait = false) {
5
5
  const addonName = addon.name || '';
6
6
  async function destroyAddonRequest() {
@@ -1,6 +1,6 @@
1
1
  import * as color from '@heroku/heroku-cli-util/color';
2
2
  import printf from 'printf';
3
- import ConfirmCommand from '../confirmCommand.js';
3
+ import ConfirmCommand from '../confirm-command.js';
4
4
  export const trapConfirmationRequired = async (app, confirm, fn) => {
5
5
  try {
6
6
  return await fn(confirm);
@@ -40,7 +40,6 @@ class TelemetryManager {
40
40
  */
41
41
  async sendTelemetry(currentTelemetry) {
42
42
  if (!isTelemetryEnabled()) {
43
- telemetryDebug('Telemetry disabled, skipping send');
44
43
  return;
45
44
  }
46
45
  const { backboardOtelClient, sentryClient } = await this.getClients();
@@ -48,12 +48,17 @@ export interface Telemetry {
48
48
  export type TelemetryData = CLIError | Telemetry;
49
49
  export interface TelemetryGlobal {
50
50
  cliTelemetry?: Telemetry;
51
+ telemetrySent?: boolean;
51
52
  }
52
53
  export type WorkerData = HerokulyticsData | TelemetryData;
53
54
  /**
54
55
  * Compute duration from a start time to now
55
56
  */
56
57
  export declare function computeDuration(cmdStartTime: number): number;
58
+ /**
59
+ * Get the reason why telemetry is disabled (for logging purposes)
60
+ */
61
+ export declare function getTelemetryDisabledReason(): null | string;
57
62
  /**
58
63
  * Get authentication token, cached to avoid recreating Config/APIClient
59
64
  * Lazy-loads @heroku-cli/command and @oclif/core/config to avoid loading them during CLI init
@@ -65,6 +70,7 @@ export declare function getToken(): Promise<string | undefined>;
65
70
  export declare function getVersion(): string;
66
71
  /**
67
72
  * Check if telemetry is enabled based on environment variables
73
+ * Returns both the enabled status and a reason string for logging
68
74
  */
69
75
  export declare function isTelemetryEnabled(): boolean;
70
76
  /**
@@ -21,6 +21,21 @@ export function computeDuration(cmdStartTime) {
21
21
  const cmdFinishTime = now.getTime();
22
22
  return cmdFinishTime - cmdStartTime;
23
23
  }
24
+ /**
25
+ * Get the reason why telemetry is disabled (for logging purposes)
26
+ */
27
+ export function getTelemetryDisabledReason() {
28
+ if (process.env.DISABLE_TELEMETRY === 'true') {
29
+ return 'DISABLE_TELEMETRY=true';
30
+ }
31
+ if (process.platform === 'win32' && process.env.ENABLE_WINDOWS_TELEMETRY !== 'true') {
32
+ return 'Windows platform requires ENABLE_WINDOWS_TELEMETRY=true';
33
+ }
34
+ if (process.env.IS_HEROKU_TEST_ENV === 'true') {
35
+ return 'IS_HEROKU_TEST_ENV=true';
36
+ }
37
+ return null;
38
+ }
24
39
  /**
25
40
  * Get authentication token, cached to avoid recreating Config/APIClient
26
41
  * Lazy-loads @heroku-cli/command and @oclif/core/config to avoid loading them during CLI init
@@ -53,14 +68,18 @@ export function getVersion() {
53
68
  }
54
69
  /**
55
70
  * Check if telemetry is enabled based on environment variables
71
+ * Returns both the enabled status and a reason string for logging
56
72
  */
57
73
  export function isTelemetryEnabled() {
58
- if (process.env.DISABLE_TELEMETRY === 'true')
74
+ if (process.env.DISABLE_TELEMETRY === 'true') {
59
75
  return false;
60
- if (process.platform === 'win32' && process.env.ENABLE_WINDOWS_TELEMETRY !== 'true')
76
+ }
77
+ if (process.platform === 'win32' && process.env.ENABLE_WINDOWS_TELEMETRY !== 'true') {
61
78
  return false;
62
- if (process.env.IS_HEROKU_TEST_ENV === 'true')
79
+ }
80
+ if (process.env.IS_HEROKU_TEST_ENV === 'true') {
63
81
  return false;
82
+ }
64
83
  return true;
65
84
  }
66
85
  /**
@@ -1,6 +1,7 @@
1
1
  import { TelemetryGlobal } from './telemetry-utils.js';
2
2
  declare global {
3
3
  var cliTelemetry: TelemetryGlobal['cliTelemetry'];
4
+ var telemetrySent: TelemetryGlobal['telemetrySent'];
4
5
  }
5
6
  interface SetupTelemetryOptions {
6
7
  cliStartTime: number;
@@ -8,9 +9,10 @@ interface SetupTelemetryOptions {
8
9
  enableTelemetry: boolean;
9
10
  }
10
11
  /**
11
- * Setup telemetry handlers for signal handlers
12
- * Note: Normal command completion telemetry is handled by the postrun hook.
13
- * This only handles SIGINT/SIGTERM cases where hooks don't run.
12
+ * Setup telemetry handlers for beforeExit and signal handlers
13
+ * - beforeExit: Fallback for commands where postrun hook doesn't run (e.g., version, --help flags)
14
+ * - postrun hook: Handles regular commands (sets telemetrySent flag to prevent duplicates)
15
+ * - SIGINT/SIGTERM: Handles interrupted commands
14
16
  */
15
17
  export declare function setupTelemetryHandlers(options: SetupTelemetryOptions): void;
16
18
  export {};
@@ -1,16 +1,30 @@
1
1
  /* eslint-disable n/no-process-exit */
2
- import { spawnTelemetryWorker } from './telemetry-utils.js';
2
+ /* eslint-disable no-var */
3
+ import { spawnTelemetryWorker, telemetryDebug, } from './telemetry-utils.js';
3
4
  /**
4
- * Setup telemetry handlers for signal handlers
5
- * Note: Normal command completion telemetry is handled by the postrun hook.
6
- * This only handles SIGINT/SIGTERM cases where hooks don't run.
5
+ * Setup telemetry handlers for beforeExit and signal handlers
6
+ * - beforeExit: Fallback for commands where postrun hook doesn't run (e.g., version, --help flags)
7
+ * - postrun hook: Handles regular commands (sets telemetrySent flag to prevent duplicates)
8
+ * - SIGINT/SIGTERM: Handles interrupted commands
7
9
  */
8
10
  export function setupTelemetryHandlers(options) {
9
11
  const { cliStartTime, computeDuration, enableTelemetry } = options;
10
12
  if (!enableTelemetry)
11
13
  return;
12
- // Note: beforeExit handler removed to avoid duplicate telemetry sends.
13
- // The postrun hook now handles normal command completion telemetry.
14
+ // Fallback handler for commands that don't trigger postrun hook
15
+ // (e.g., version, --version, --help flags handled by oclif)
16
+ process.once('beforeExit', code => {
17
+ // Only send if telemetry wasn't already sent by postrun hook
18
+ if (global.cliTelemetry && !global.telemetrySent) {
19
+ telemetryDebug('Telemetry enabled: beforeExit spawning worker to send telemetry for command: %s (postrun did not run)', global.cliTelemetry.command);
20
+ const cmdStartTime = global.cliTelemetry.commandRunDuration;
21
+ global.cliTelemetry.commandRunDuration = computeDuration(cmdStartTime);
22
+ global.cliTelemetry.exitCode = code;
23
+ global.cliTelemetry.cliRunDuration = computeDuration(cliStartTime);
24
+ spawnTelemetryWorker(global.cliTelemetry);
25
+ global.telemetrySent = true;
26
+ }
27
+ });
14
28
  process.on('SIGINT', () => {
15
29
  // Spawn background process to send telemetry
16
30
  const error = Object.assign(new Error('Received SIGINT'), {
@@ -1,2 +1,2 @@
1
- import { SniEndpoint } from '../types/sni_endpoint.js';
1
+ import { SniEndpoint } from '../types/sni-endpoint.js';
2
2
  export declare const displayCertificateDetails: (sniEndpoint: SniEndpoint, message?: string) => void;