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.
- package/lib/commands/addons/index.d.ts +1 -1
- package/lib/commands/addons/index.js +4 -4
- package/lib/commands/pg/copy.d.ts +6 -6
- package/lib/commands/pg/copy.js +16 -16
- package/lib/commands/pg/credentials/url.js +3 -5
- package/lib/commands/pg/credentials.d.ts +7 -7
- package/lib/commands/pg/credentials.js +10 -10
- package/lib/commands/webhooks/add.d.ts +16 -0
- package/lib/commands/webhooks/add.js +43 -0
- package/lib/commands/webhooks/deliveries/index.d.ts +12 -0
- package/lib/commands/webhooks/deliveries/index.js +75 -0
- package/lib/commands/webhooks/deliveries/info.d.ts +14 -0
- package/lib/commands/webhooks/deliveries/info.js +40 -0
- package/lib/commands/webhooks/index.d.ts +11 -0
- package/lib/commands/webhooks/index.js +42 -0
- package/lib/commands/webhooks/info.d.ts +14 -0
- package/lib/commands/webhooks/info.js +29 -0
- package/lib/commands/webhooks/remove.d.ts +14 -0
- package/lib/commands/webhooks/remove.js +24 -0
- package/lib/commands/webhooks/update.d.ts +19 -0
- package/lib/commands/webhooks/update.js +36 -0
- package/lib/lib/addons/util.js +1 -2
- package/lib/lib/data/credentialUtils.js +1 -1
- package/lib/lib/data/types.d.ts +10 -6
- package/lib/lib/pg/types.d.ts +0 -18
- package/lib/lib/pg/util.d.ts +2 -2
- package/lib/lib/pg/util.js +5 -0
- package/lib/lib/run/dyno.d.ts +3 -11
- package/lib/lib/run/dyno.js +15 -18
- package/lib/lib/utils/multisort.d.ts +4 -7
- package/lib/lib/utils/multisort.js +8 -32
- package/npm-shrinkwrap.json +1 -1
- package/oclif.manifest.json +1468 -1005
- package/package.json +2 -2
- package/lib/oldCommands/webhooks/add.d.ts +0 -1
- package/lib/oldCommands/webhooks/add.js +0 -56
- package/lib/oldCommands/webhooks/deliveries/index.d.ts +0 -1
- package/lib/oldCommands/webhooks/deliveries/index.js +0 -90
- package/lib/oldCommands/webhooks/deliveries/info.d.ts +0 -1
- package/lib/oldCommands/webhooks/deliveries/info.js +0 -54
- package/lib/oldCommands/webhooks/index.d.ts +0 -1
- package/lib/oldCommands/webhooks/index.js +0 -55
- package/lib/oldCommands/webhooks/info.d.ts +0 -1
- package/lib/oldCommands/webhooks/info.js +0 -41
- package/lib/oldCommands/webhooks/remove.d.ts +0 -1
- package/lib/oldCommands/webhooks/remove.js +0 -37
- package/lib/oldCommands/webhooks/update.d.ts +0 -1
- package/lib/oldCommands/webhooks/update.js +0 -50
package/lib/lib/addons/util.js
CHANGED
|
@@ -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
|
|
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:
|
|
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)
|
package/lib/lib/data/types.d.ts
CHANGED
|
@@ -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:
|
|
175
|
+
state: NonAdvancedCredentialStoreState;
|
|
172
176
|
uuid: string;
|
|
173
177
|
}
|
|
174
178
|
export declare type ExtendedPostgresLevelInfo = {
|
package/lib/lib/pg/types.d.ts
CHANGED
|
@@ -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
|
};
|
package/lib/lib/pg/util.d.ts
CHANGED
|
@@ -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
|
|
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:
|
|
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;
|
package/lib/lib/pg/util.js
CHANGED
|
@@ -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') {
|
package/lib/lib/run/dyno.d.ts
CHANGED
|
@@ -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>;
|
package/lib/lib/run/dyno.js
CHANGED
|
@@ -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
|
|
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 =>
|
|
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 =
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
1
|
+
export declare type Comparator = (a: any, b: any) => number;
|
|
2
2
|
/**
|
|
3
|
-
* The multiSortCompareFn function is used to
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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
|
-
*
|
|
4
|
-
*
|
|
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
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
36
|
+
return 0;
|
|
61
37
|
};
|
|
62
38
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -20856,7 +20856,7 @@
|
|
|
20856
20856
|
},
|
|
20857
20857
|
"packages/cli": {
|
|
20858
20858
|
"name": "heroku",
|
|
20859
|
-
"version": "11.0.0-alpha.
|
|
20859
|
+
"version": "11.0.0-alpha.13",
|
|
20860
20860
|
"license": "ISC",
|
|
20861
20861
|
"dependencies": {
|
|
20862
20862
|
"@heroku-cli/command": "^12.1.1",
|