heroku 11.0.0-alpha.12 → 11.0.0-alpha.13

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 (48) hide show
  1. package/lib/commands/addons/index.d.ts +1 -1
  2. package/lib/commands/addons/index.js +4 -4
  3. package/lib/commands/pg/copy.d.ts +6 -6
  4. package/lib/commands/pg/copy.js +16 -16
  5. package/lib/commands/pg/credentials/url.js +3 -5
  6. package/lib/commands/pg/credentials.d.ts +7 -7
  7. package/lib/commands/pg/credentials.js +10 -10
  8. package/lib/commands/webhooks/add.d.ts +16 -0
  9. package/lib/commands/webhooks/add.js +43 -0
  10. package/lib/commands/webhooks/deliveries/index.d.ts +12 -0
  11. package/lib/commands/webhooks/deliveries/index.js +75 -0
  12. package/lib/commands/webhooks/deliveries/info.d.ts +14 -0
  13. package/lib/commands/webhooks/deliveries/info.js +40 -0
  14. package/lib/commands/webhooks/index.d.ts +11 -0
  15. package/lib/commands/webhooks/index.js +42 -0
  16. package/lib/commands/webhooks/info.d.ts +14 -0
  17. package/lib/commands/webhooks/info.js +29 -0
  18. package/lib/commands/webhooks/remove.d.ts +14 -0
  19. package/lib/commands/webhooks/remove.js +24 -0
  20. package/lib/commands/webhooks/update.d.ts +19 -0
  21. package/lib/commands/webhooks/update.js +36 -0
  22. package/lib/lib/addons/util.js +1 -2
  23. package/lib/lib/data/credentialUtils.js +1 -1
  24. package/lib/lib/data/types.d.ts +10 -6
  25. package/lib/lib/pg/types.d.ts +0 -18
  26. package/lib/lib/pg/util.d.ts +2 -2
  27. package/lib/lib/pg/util.js +5 -0
  28. package/lib/lib/run/dyno.d.ts +3 -11
  29. package/lib/lib/run/dyno.js +15 -18
  30. package/lib/lib/utils/multisort.d.ts +4 -7
  31. package/lib/lib/utils/multisort.js +8 -32
  32. package/npm-shrinkwrap.json +1 -1
  33. package/oclif.manifest.json +1468 -1005
  34. package/package.json +2 -2
  35. package/lib/oldCommands/webhooks/add.d.ts +0 -1
  36. package/lib/oldCommands/webhooks/add.js +0 -56
  37. package/lib/oldCommands/webhooks/deliveries/index.d.ts +0 -1
  38. package/lib/oldCommands/webhooks/deliveries/index.js +0 -90
  39. package/lib/oldCommands/webhooks/deliveries/info.d.ts +0 -1
  40. package/lib/oldCommands/webhooks/deliveries/info.js +0 -54
  41. package/lib/oldCommands/webhooks/index.d.ts +0 -1
  42. package/lib/oldCommands/webhooks/index.js +0 -55
  43. package/lib/oldCommands/webhooks/info.d.ts +0 -1
  44. package/lib/oldCommands/webhooks/info.js +0 -41
  45. package/lib/oldCommands/webhooks/remove.d.ts +0 -1
  46. package/lib/oldCommands/webhooks/remove.js +0 -37
  47. package/lib/oldCommands/webhooks/update.d.ts +0 -1
  48. package/lib/oldCommands/webhooks/update.js +0 -50
@@ -1,7 +1,6 @@
1
1
  import { color } from '@heroku/heroku-cli-util';
2
2
  import printf from 'printf';
3
3
  import ConfirmCommand from '../confirmCommand.js';
4
- const confirmCommand = new ConfirmCommand();
5
4
  export const trapConfirmationRequired = async (app, confirm, fn) => {
6
5
  try {
7
6
  return await fn(confirm);
@@ -10,7 +9,7 @@ export const trapConfirmationRequired = async (app, confirm, fn) => {
10
9
  if (!isHttpError(error) || error.body?.id !== 'confirmation_required') {
11
10
  throw error;
12
11
  }
13
- await confirmCommand.confirm(app, confirm, error.body.message);
12
+ await new ConfirmCommand().confirm(app, confirm, error.body.message);
14
13
  return fn(app);
15
14
  }
16
15
  };
@@ -1,5 +1,5 @@
1
1
  // NEW This is new. something similar exists in core: packages/cli/src/commands/pg/credentials.ts:61
2
- // protected sortByDefaultAndName(credentials: CredentialsInfo) {
2
+ // protected sortByDefaultAndName(credentials: CredentialInfo[]) {
3
3
  // return credentials.sort((a, b) => {
4
4
  // const isDefaultA = this.isDefaultCredential(a)
5
5
  // const isDefaultB = this.isDefaultCredential(b)
@@ -158,17 +158,21 @@ export declare type PricingInfo = {
158
158
  };
159
159
  export declare type TierPricingInfo = Record<string, PricingInfo>;
160
160
  export declare type PricingInfoResponse = Record<string, TierPricingInfo>;
161
+ declare type NonAdvancedCredentialState = 'active' | 'archived' | 'enabling' | 'revoked' | 'revoking';
162
+ declare type NonAdvancedCredential = {
163
+ connections?: null | number;
164
+ password: string;
165
+ state: NonAdvancedCredentialState;
166
+ user: string;
167
+ };
168
+ declare type NonAdvancedCredentialStoreState = 'active' | 'archived' | 'provisioning' | 'revoking' | 'rotating' | 'rotation_completed' | 'wait_for_provisioning';
161
169
  export interface NonAdvancedCredentialInfo extends Record<string, unknown> {
162
- credentials: Array<{
163
- password: string;
164
- state: string;
165
- user: string;
166
- }>;
170
+ credentials: Array<NonAdvancedCredential>;
167
171
  database: string;
168
172
  host: string;
169
173
  name: string;
170
174
  port: string;
171
- state: string;
175
+ state: NonAdvancedCredentialStoreState;
172
176
  uuid: string;
173
177
  }
174
178
  export declare type ExtendedPostgresLevelInfo = {
@@ -138,24 +138,6 @@ export declare type Link = {
138
138
  attachment_name: string;
139
139
  };
140
140
  };
141
- declare type CredentialState = 'enabling' | 'active' | 'revoking' | 'revoked' | 'archived';
142
- export declare type Credential = {
143
- user: string;
144
- password: string;
145
- state: CredentialState;
146
- connections?: number | null;
147
- };
148
- declare type CredentialStoreState = 'provisioning' | 'wait_for_provisioning' | 'active' | 'rotating' | 'rotation_completed' | 'revoking' | 'archived';
149
- export declare type CredentialInfo = {
150
- uuid: string;
151
- name: string;
152
- state: CredentialStoreState;
153
- database: string;
154
- host: string;
155
- port: number;
156
- credentials: Array<Credential>;
157
- };
158
- export declare type CredentialsInfo = Array<CredentialInfo>;
159
141
  export declare type MaintenanceApiResponse = {
160
142
  message: string;
161
143
  };
@@ -1,8 +1,8 @@
1
1
  import type { AddOnAttachment } from '@heroku-cli/schema';
2
2
  import { pg } from '@heroku/heroku-cli-util';
3
- import type { CredentialsInfo } from './types.js';
3
+ import { type CredentialInfo } from '../../lib/data/types.js';
4
4
  export declare function essentialPlan(addon: pg.ExtendedAddon | pg.ExtendedAddonAttachment['addon']): boolean;
5
5
  export declare function formatResponseWithCommands(response: string): string;
6
- export declare function presentCredentialAttachments(app: string, credAttachments: Required<AddOnAttachment>[], credentials: CredentialsInfo, cred: string): string;
6
+ export declare function presentCredentialAttachments(app: string, credAttachments: Required<AddOnAttachment>[], credentials: CredentialInfo[], cred: string): string;
7
7
  export declare const configVarNamesFromValue: (config: Record<string, string>, value: string) => string[];
8
8
  export declare const databaseNameFromUrl: (uri: string, config: Record<string, string>) => string;
@@ -1,5 +1,6 @@
1
1
  import { color, hux, utils, } from '@heroku/heroku-cli-util';
2
2
  import { renderAttachment } from '../../commands/addons/index.js';
3
+ import { isAdvancedCredentialInfo } from '../../lib/data/types.js';
3
4
  import { multiSortCompareFn } from '../utils/multisort.js';
4
5
  export function essentialPlan(addon) {
5
6
  return utils.pg.isEssentialDatabase(addon) || utils.pg.isLegacyEssentialDatabase(addon);
@@ -24,6 +25,10 @@ export function presentCredentialAttachments(app, credAttachments, credentials,
24
25
  const isLast = (idx === credAttachments.length - 1);
25
26
  return renderAttachment(attachment, app, isLast);
26
27
  });
28
+ // We would use utils.pg.isAdvancedDatabase from @heroku/heroku-cli-util, but we're not passing the add-on as a parameter.
29
+ if (credentials.length > 0 && isAdvancedCredentialInfo(credentials[0])) {
30
+ return [cred, ...attLines].join('\n');
31
+ }
27
32
  const rotationLines = [];
28
33
  const credentialStore = credentials.find(a => a.name === cred);
29
34
  if (credentialStore?.state === 'rotating') {
@@ -3,7 +3,7 @@
3
3
  /// <reference types="node" resolution-mode="require"/>
4
4
  /// <reference types="node" resolution-mode="require"/>
5
5
  import { HTTP } from '@heroku/http-call';
6
- import { APIClient } from '@heroku-cli/command';
6
+ import { APIClient, type IOptions } from '@heroku-cli/command';
7
7
  import { Dyno as APIDyno } from '@heroku-cli/schema';
8
8
  import * as net from 'net';
9
9
  import { Duplex } from 'stream';
@@ -14,7 +14,7 @@ interface HerokuApiClientRun extends APIClient {
14
14
  rejectUnauthorized?: boolean;
15
15
  } & IOptions;
16
16
  }
17
- interface DynoOpts {
17
+ export interface DynoOpts {
18
18
  app: string;
19
19
  attach?: boolean;
20
20
  command: string;
@@ -24,17 +24,12 @@ interface DynoOpts {
24
24
  heroku: APIClient;
25
25
  listen?: boolean;
26
26
  'no-tty'?: boolean;
27
+ notificationSubtitle?: string;
27
28
  notify?: boolean;
28
29
  showStatus?: boolean;
29
30
  size?: string;
30
31
  type?: string;
31
32
  }
32
- interface IOptions {
33
- debug?: boolean;
34
- debugHeaders?: boolean;
35
- preauth?: boolean;
36
- required?: boolean;
37
- }
38
33
  export default class Dyno extends Duplex {
39
34
  opts: DynoOpts;
40
35
  dyno?: APIDyno;
@@ -53,9 +48,6 @@ export default class Dyno extends Duplex {
53
48
  private _startedAt?;
54
49
  constructor(opts: DynoOpts);
55
50
  attach(): any;
56
- /**
57
- * Starts the dyno
58
- */
59
51
  start(): Promise<void>;
60
52
  _connect(): Promise<unknown>;
61
53
  _doStart(retries?: number): Promise<HTTP<unknown> | undefined>;
@@ -1,18 +1,21 @@
1
1
  /* eslint-disable @typescript-eslint/ban-ts-comment */
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
3
  import { color } from '@heroku/heroku-cli-util';
3
4
  import { notify } from '@heroku-cli/notifications';
4
5
  import { ux } from '@oclif/core';
5
- import { spawn } from 'child_process';
6
6
  import debugFactory from 'debug';
7
7
  import * as https from 'https';
8
8
  import * as net from 'net';
9
+ import { spawn } from 'node:child_process';
9
10
  import { Duplex, Transform } from 'stream';
10
11
  import * as tls from 'tls';
11
12
  import * as tty from 'tty';
12
- import { URL, parse } from 'url';
13
+ import { URL } from 'url';
13
14
  import { buildEnvFromFlag } from './helpers.js';
14
15
  const debug = debugFactory('heroku:run');
15
- const wait = (ms) => new Promise(resolve => setTimeout(() => resolve(), ms));
16
+ const wait = (ms) => new Promise(resolve => {
17
+ setTimeout(() => resolve(), ms);
18
+ });
16
19
  export default class Dyno extends Duplex {
17
20
  opts;
18
21
  dyno;
@@ -42,7 +45,7 @@ export default class Dyno extends Duplex {
42
45
  this.pipe(process.stdout);
43
46
  if (this.dyno && this.dyno.attach_url) {
44
47
  this.uri = new URL(this.dyno.attach_url);
45
- this.legacyUri = parse(this.dyno.attach_url);
48
+ this.legacyUri = new URL(this.dyno.attach_url);
46
49
  }
47
50
  if (this._useSSH) {
48
51
  this.p = this._ssh();
@@ -54,9 +57,7 @@ export default class Dyno extends Duplex {
54
57
  this.end();
55
58
  });
56
59
  }
57
- /**
58
- * Starts the dyno
59
- */
60
+ // Starts the dyno
60
61
  async start() {
61
62
  this._startedAt = Date.now();
62
63
  if (this.opts.showStatus) {
@@ -168,7 +169,7 @@ export default class Dyno extends Duplex {
168
169
  // does not actually uncork but allows error to be displayed when attempting to read
169
170
  this.uncork();
170
171
  if (this.opts.listen) {
171
- ux.stderr(`listening on port ${host}:${port} for ssh client`);
172
+ ux.stdout(`listening on port ${host}:${port} for ssh client`);
172
173
  }
173
174
  else {
174
175
  const params = [host, '-p', port.toString(), '-oStrictHostKeyChecking=no', '-oUserKnownHostsFile=/dev/null', '-oServerAliveInterval=20'];
@@ -247,11 +248,9 @@ export default class Dyno extends Duplex {
247
248
  if (Date.now() - this._startedAt < 1000 * 20)
248
249
  return;
249
250
  const notification = {
250
- // @ts-ignore
251
251
  message: 'dyno is up',
252
- subtitle: `heroku run ${this.opts.command}`,
252
+ subtitle: this.opts.notificationSubtitle || `heroku run ${this.opts.command}`,
253
253
  title: this.opts.app,
254
- // sound: true
255
254
  };
256
255
  notify(notification);
257
256
  }
@@ -280,8 +279,7 @@ export default class Dyno extends Duplex {
280
279
  this._notify();
281
280
  // carriage returns break json parsing of output
282
281
  if (!process.stdout.isTTY) {
283
- // eslint-disable-next-line no-control-regex, prefer-regex-literals
284
- data = data.replace(new RegExp('\r\n', 'g'), '\n');
282
+ data = data.replaceAll('\r\n', '\n');
285
283
  }
286
284
  const exitCode = data.match(/\uFFFF heroku-command-exit-status: (\d+)/m);
287
285
  if (exitCode) {
@@ -329,8 +327,7 @@ export default class Dyno extends Duplex {
329
327
  }
330
328
  else {
331
329
  stdin.pipe(new Transform({
332
- // eslint-disable-next-line unicorn/no-hex-escape
333
- flush: done => c.write('\x04', done),
330
+ flush: done => c.write('\u0004', done),
334
331
  objectMode: true,
335
332
  transform: (chunk, _, next) => c.write(chunk, next),
336
333
  }));
@@ -351,7 +348,7 @@ export default class Dyno extends Duplex {
351
348
  c.setTimeout(1000 * 60 * 60);
352
349
  c.setEncoding('utf8');
353
350
  c.on('connect', () => {
354
- debug('connect');
351
+ debug('dyno connect');
355
352
  // @ts-ignore eslint-disable-next-line no-unsafe-optional-chaining
356
353
  const pathnameWithSearchParams = this.uri.pathname + this.uri.search;
357
354
  c.write(pathnameWithSearchParams.slice(1) + '\r\n', () => {
@@ -362,7 +359,7 @@ export default class Dyno extends Duplex {
362
359
  });
363
360
  c.on('data', this._readData(c));
364
361
  c.on('close', () => {
365
- debug('close');
362
+ debug('dyno connection close');
366
363
  // @ts-ignore
367
364
  this.opts['exit-code'] ? this.reject('No exit code returned') : this.resolve();
368
365
  if (this.unpipeStdin) {
@@ -371,7 +368,7 @@ export default class Dyno extends Duplex {
371
368
  });
372
369
  c.on('error', this.reject);
373
370
  c.on('timeout', () => {
374
- debug('timeout');
371
+ debug('dyno timeout');
375
372
  c.end();
376
373
  // @ts-ignore
377
374
  this.reject(new Error('timed out'));
@@ -1,11 +1,8 @@
1
- export declare type Comparator = Parameters<typeof Array.prototype.sort>[0];
1
+ export declare type Comparator = (a: any, b: any) => number;
2
2
  /**
3
- * The multiSortCompareFn function is used to
4
- * build a single comparator function for use
5
- * in Array.sort when multiple sort criteria
6
- * is needed on an object type. The indices of
7
- * specified array of SortCriteria indicate the
8
- * precedence of each comparator.
3
+ * The multiSortCompareFn function is used to build a single comparator function for use
4
+ * in Array.sort when multiple sort criteria is needed on an object type. The indices of
5
+ * specified array of SortCriteria indicates the precedence of each comparator.
9
6
  *
10
7
  * @example
11
8
  * ```ts
@@ -1,10 +1,7 @@
1
1
  /**
2
- * The multiSortCompareFn function is used to
3
- * build a single comparator function for use
4
- * in Array.sort when multiple sort criteria
5
- * is needed on an object type. The indices of
6
- * specified array of SortCriteria indicate the
7
- * precedence of each comparator.
2
+ * The multiSortCompareFn function is used to build a single comparator function for use
3
+ * in Array.sort when multiple sort criteria is needed on an object type. The indices of
4
+ * specified array of SortCriteria indicates the precedence of each comparator.
8
5
  *
9
6
  * @example
10
7
  * ```ts
@@ -29,34 +26,13 @@
29
26
  * @returns Comparator
30
27
  */
31
28
  export function multiSortCompareFn(comparators) {
32
- // Typical bitmask strategy whereas the most
33
- // significant bit represents the comparator
34
- // result in the zero index and thus has the
35
- // highest precedence. The bit length
36
- // is determined by the number of comparators
37
- // and the positional notation mirrors the
38
- // comparator indices.
39
- // There is a 32 bit limit in total. 2 bits
40
- // are used for 1. the bitLength and 2. the two's
41
- // compliment signed bit. This means we have a
42
- // limit of 30 comparators max.
43
29
  return (a, b) => {
44
- const bitLen = comparators.length - 1;
45
- let bitA = 0;
46
- let bitB = 0;
47
- for (const [i, comparator] of comparators.entries()) {
48
- const priority = 1 << (bitLen - i);
49
- const score = comparator?.(a, b);
50
- if (score === -1) {
51
- bitA |= priority;
52
- }
53
- if (score === 1) {
54
- bitB |= priority;
55
- }
56
- if (bitA !== bitB) {
57
- break;
30
+ for (const comparator of comparators) {
31
+ const comparison = comparator(a, b);
32
+ if (comparison !== 0) {
33
+ return comparison;
58
34
  }
59
35
  }
60
- return bitA > bitB ? -1 : (bitA < bitB ? 1 : 0);
36
+ return 0;
61
37
  };
62
38
  }
@@ -20856,7 +20856,7 @@
20856
20856
  },
20857
20857
  "packages/cli": {
20858
20858
  "name": "heroku",
20859
- "version": "11.0.0-alpha.12",
20859
+ "version": "11.0.0-alpha.13",
20860
20860
  "license": "ISC",
20861
20861
  "dependencies": {
20862
20862
  "@heroku-cli/command": "^12.1.1",