heroku 9.0.0 → 9.1.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.
- package/lib/commands/autocomplete/options.js +1 -1
- package/lib/commands/config/edit.js +1 -1
- package/lib/commands/container/push.js +3 -0
- package/lib/commands/domains/index.d.ts +4 -0
- package/lib/commands/domains/index.js +47 -3
- package/lib/lib/ci/interfaces/kolkrabbi.d.ts +1 -1
- package/lib/lib/container/helpers.js +7 -4
- package/lib/lib/pg/fetcher.js +0 -1
- package/lib/lib/utils/keyValueParser.d.ts +4 -0
- package/lib/lib/utils/keyValueParser.js +9 -0
- package/lib/lib/utils/paginator.d.ts +2 -0
- package/lib/lib/utils/paginator.js +29 -0
- package/oclif.manifest.json +29 -29
- package/package.json +3 -2
|
@@ -16,7 +16,7 @@ class Options extends base_1.AutocompleteBase {
|
|
|
16
16
|
// *args: refers to a Command's static args
|
|
17
17
|
// *argv: refers to the current execution's command line positional input
|
|
18
18
|
// Klass: (class) Command class
|
|
19
|
-
// completion: (object) object with data/methods to build/
|
|
19
|
+
// completion: (object) object with data/methods to build/retrieve options from cache
|
|
20
20
|
// curPosition*: the current argv position the shell is trying to complete
|
|
21
21
|
// options: (string) white-space separated list of values for the shell to use for completion
|
|
22
22
|
async run() {
|
|
@@ -20,7 +20,7 @@ function removeDeleted(newConfig, original) {
|
|
|
20
20
|
for (const k of Object.keys(original)) {
|
|
21
21
|
// The api accepts empty strings
|
|
22
22
|
// as valid env var values
|
|
23
|
-
// In JS an empty string is
|
|
23
|
+
// In JS an empty string is false
|
|
24
24
|
if (!newConfig[k] && newConfig[k] !== '')
|
|
25
25
|
newConfig[k] = null;
|
|
26
26
|
}
|
|
@@ -15,6 +15,9 @@ async function selectJobs(jobs, processTypes, recursive) {
|
|
|
15
15
|
if (processTypes.length > 0) {
|
|
16
16
|
filteredJobs = DockerHelper.filterByProcessType(jobs, processTypes);
|
|
17
17
|
}
|
|
18
|
+
else {
|
|
19
|
+
filteredJobs = jobs;
|
|
20
|
+
}
|
|
18
21
|
selectedJobs = await DockerHelper.chooseJobs(filteredJobs);
|
|
19
22
|
}
|
|
20
23
|
else if (jobs.standard) {
|
|
@@ -36,5 +36,9 @@ export default class DomainsIndex extends Command {
|
|
|
36
36
|
extended: boolean;
|
|
37
37
|
};
|
|
38
38
|
};
|
|
39
|
+
getFilteredDomains: (filterKeyValue: string, domains: Array<Heroku.Domain>) => {
|
|
40
|
+
size: number;
|
|
41
|
+
filteredDomains: Heroku.Domain[];
|
|
42
|
+
};
|
|
39
43
|
run(): Promise<void>;
|
|
40
44
|
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const command_1 = require("@heroku-cli/command");
|
|
4
|
+
const color_1 = require("@heroku-cli/color");
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
6
|
const Uri = require("urijs");
|
|
7
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
8
|
+
const paginator_1 = require("../../lib/utils/paginator");
|
|
9
|
+
const keyValueParser_1 = require("../../lib/utils/keyValueParser");
|
|
6
10
|
function isApexDomain(hostname) {
|
|
7
11
|
if (hostname.includes('*'))
|
|
8
12
|
return false;
|
|
@@ -44,12 +48,44 @@ class DomainsIndex extends command_1.Command {
|
|
|
44
48
|
}
|
|
45
49
|
return tableConfig;
|
|
46
50
|
};
|
|
51
|
+
this.getFilteredDomains = (filterKeyValue, domains) => {
|
|
52
|
+
const filteredInfo = { size: 0, filteredDomains: domains };
|
|
53
|
+
const { key: filterName, value } = (0, keyValueParser_1.default)(filterKeyValue);
|
|
54
|
+
if (!value) {
|
|
55
|
+
throw new Error('Filter flag has an invalid value');
|
|
56
|
+
}
|
|
57
|
+
if (filterName === 'Domain Name') {
|
|
58
|
+
filteredInfo.filteredDomains = domains.filter(domain => domain.hostname.includes(value));
|
|
59
|
+
}
|
|
60
|
+
if (filterName === 'DNS Record Type') {
|
|
61
|
+
filteredInfo.filteredDomains = domains.filter(domain => {
|
|
62
|
+
const kind = isApexDomain(domain.hostname) ? 'ALIAS or ANAME' : 'CNAME';
|
|
63
|
+
return kind.includes(value);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (filterName === 'DNS Target') {
|
|
67
|
+
filteredInfo.filteredDomains = domains.filter(domain => domain.cname.includes(value));
|
|
68
|
+
}
|
|
69
|
+
if (filterName === 'SNI Endpoint') {
|
|
70
|
+
filteredInfo.filteredDomains = domains.filter(domain => {
|
|
71
|
+
if (!domain.sni_endpoint)
|
|
72
|
+
domain.sni_endpoint = '';
|
|
73
|
+
return domain.sni_endpoint.includes(value);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
filteredInfo.size = filteredInfo.filteredDomains.length;
|
|
77
|
+
return filteredInfo;
|
|
78
|
+
};
|
|
47
79
|
}
|
|
48
80
|
async run() {
|
|
49
81
|
const { flags } = await this.parse(DomainsIndex);
|
|
50
|
-
const
|
|
51
|
-
const herokuDomain = domains.find(domain => domain.kind === 'heroku');
|
|
52
|
-
|
|
82
|
+
const domains = await (0, paginator_1.paginateRequest)(this.heroku, `/apps/${flags.app}/domains`, 1000);
|
|
83
|
+
const herokuDomain = domains.find((domain) => domain.kind === 'heroku');
|
|
84
|
+
let customDomains = domains.filter((domain) => domain.kind === 'custom');
|
|
85
|
+
let displayTotalDomains = false;
|
|
86
|
+
if (flags.filter) {
|
|
87
|
+
customDomains = this.getFilteredDomains(flags.filter, domains).filteredDomains;
|
|
88
|
+
}
|
|
53
89
|
if (flags.json) {
|
|
54
90
|
core_1.ux.styledJSON(domains);
|
|
55
91
|
}
|
|
@@ -57,6 +93,14 @@ class DomainsIndex extends command_1.Command {
|
|
|
57
93
|
core_1.ux.styledHeader(`${flags.app} Heroku Domain`);
|
|
58
94
|
core_1.ux.log(herokuDomain && herokuDomain.hostname);
|
|
59
95
|
if (customDomains && customDomains.length > 0) {
|
|
96
|
+
core_1.ux.log();
|
|
97
|
+
if (customDomains.length > 100 && !flags.csv) {
|
|
98
|
+
core_1.ux.warn(`This app has over 100 domains. Your terminal may not be configured to display the total amount of domains. You can export all domains into a CSV file with: ${color_1.default.cyan('heroku domains -a example-app --csv > example-file.csv')}`);
|
|
99
|
+
displayTotalDomains = await (0, prompts_1.confirm)({ default: false, message: `Display all ${customDomains.length} domains?`, theme: { prefix: '', style: { defaultAnswer: () => '(Y/N)' } } });
|
|
100
|
+
if (!displayTotalDomains) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
60
104
|
core_1.ux.log();
|
|
61
105
|
core_1.ux.styledHeader(`${flags.app} Custom Domains`);
|
|
62
106
|
core_1.ux.table(customDomains, this.tableConfig(true), Object.assign(Object.assign({}, flags), { 'no-truncate': true }));
|
|
@@ -240,7 +240,7 @@ export interface HerokuPlatformApiPipeline {
|
|
|
240
240
|
[k: string]: any;
|
|
241
241
|
}
|
|
242
242
|
/**
|
|
243
|
-
* A Repository is a reference to a remote
|
|
243
|
+
* A Repository is a reference to a remote DVCS codebase
|
|
244
244
|
*/
|
|
245
245
|
export interface KolkrabbiApiRepositories {
|
|
246
246
|
/**
|
|
@@ -13,12 +13,15 @@ const stackLabelMap = {
|
|
|
13
13
|
* @returns {null} null
|
|
14
14
|
*/
|
|
15
15
|
function ensureContainerStack(app, cmd) {
|
|
16
|
-
var _a, _b
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
var _a, _b;
|
|
17
|
+
const buildStack = (_a = app.build_stack) === null || _a === void 0 ? void 0 : _a.name;
|
|
18
|
+
const appStack = (_b = app.stack) === null || _b === void 0 ? void 0 : _b.name;
|
|
19
|
+
const allowedStack = 'container';
|
|
20
|
+
// either can be container stack and are allowed
|
|
21
|
+
if (buildStack !== allowedStack && appStack !== allowedStack) {
|
|
19
22
|
let message = 'This command is for Docker apps only.';
|
|
20
23
|
if (['push', 'release'].includes(cmd)) {
|
|
21
|
-
message += `
|
|
24
|
+
message += ` Switch stacks by running ${color_1.default.cmd('heroku stack:set container')}. Or, to deploy ${color_1.default.app(app.name)} with ${color_1.default.yellow(appStack)}, run ${color_1.default.cmd('git push heroku main')} instead.`;
|
|
22
25
|
}
|
|
23
26
|
core_1.ux.error(message, { exit: 1 });
|
|
24
27
|
}
|
package/lib/lib/pg/fetcher.js
CHANGED
|
@@ -86,7 +86,6 @@ async function getAttachment(heroku, app, db = 'DATABASE_URL', namespace = '') {
|
|
|
86
86
|
if (attachments.length === 0) {
|
|
87
87
|
throw new Error(`${color_1.default.app(app)} has no databases`);
|
|
88
88
|
}
|
|
89
|
-
console.log('hi', JSON.stringify(attachments));
|
|
90
89
|
matches = attachments.filter(attachment => config[db] && config[db] === config[(0, util_1.getConfigVarName)(attachment.config_vars)]);
|
|
91
90
|
if (matches.length === 0) {
|
|
92
91
|
const validOptions = attachments.map(attachment => (0, util_1.getConfigVarName)(attachment.config_vars));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function parseKeyValue(input) {
|
|
4
|
+
let [key, value] = input.split(/=(.+)/);
|
|
5
|
+
key = key.trim();
|
|
6
|
+
value = value ? value.trim() : '';
|
|
7
|
+
return { key, value };
|
|
8
|
+
}
|
|
9
|
+
exports.default = parseKeyValue;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// page size ranges from 200 - 1000 seen here
|
|
3
|
+
// https://devcenter.heroku.com/articles/platform-api-reference#ranges
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.paginateRequest = void 0;
|
|
6
|
+
async function paginateRequest(client, url, pageSize = 200) {
|
|
7
|
+
let isPartial = true;
|
|
8
|
+
let isFirstRequest = true;
|
|
9
|
+
let nextRange = '';
|
|
10
|
+
let aggregatedResponseBody = [];
|
|
11
|
+
while (isPartial) {
|
|
12
|
+
const response = await client.get(url, {
|
|
13
|
+
headers: {
|
|
14
|
+
Range: `${(isPartial && !isFirstRequest) ? `${nextRange}` : `id ..; max=${pageSize};`}`,
|
|
15
|
+
},
|
|
16
|
+
partial: true,
|
|
17
|
+
});
|
|
18
|
+
aggregatedResponseBody = [...response.body, ...aggregatedResponseBody];
|
|
19
|
+
isFirstRequest = false;
|
|
20
|
+
if (response.statusCode === 206) {
|
|
21
|
+
nextRange = response.headers['next-range'];
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
isPartial = false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return aggregatedResponseBody;
|
|
28
|
+
}
|
|
29
|
+
exports.paginateRequest = paginateRequest;
|
package/oclif.manifest.json
CHANGED
|
@@ -9256,34 +9256,6 @@
|
|
|
9256
9256
|
"index.js"
|
|
9257
9257
|
]
|
|
9258
9258
|
},
|
|
9259
|
-
"teams": {
|
|
9260
|
-
"aliases": [],
|
|
9261
|
-
"args": {},
|
|
9262
|
-
"description": "list the teams that you are a member of\n\nUse heroku members:* to manage team members.",
|
|
9263
|
-
"flags": {
|
|
9264
|
-
"json": {
|
|
9265
|
-
"description": "output in json format",
|
|
9266
|
-
"name": "json",
|
|
9267
|
-
"allowNo": false,
|
|
9268
|
-
"type": "boolean"
|
|
9269
|
-
}
|
|
9270
|
-
},
|
|
9271
|
-
"hasDynamicHelp": false,
|
|
9272
|
-
"hiddenAliases": [],
|
|
9273
|
-
"id": "teams",
|
|
9274
|
-
"pluginAlias": "heroku",
|
|
9275
|
-
"pluginName": "heroku",
|
|
9276
|
-
"pluginType": "core",
|
|
9277
|
-
"strict": true,
|
|
9278
|
-
"topic": "teams",
|
|
9279
|
-
"isESM": false,
|
|
9280
|
-
"relativePath": [
|
|
9281
|
-
"lib",
|
|
9282
|
-
"commands",
|
|
9283
|
-
"teams",
|
|
9284
|
-
"index.js"
|
|
9285
|
-
]
|
|
9286
|
-
},
|
|
9287
9259
|
"spaces:create": {
|
|
9288
9260
|
"aliases": [],
|
|
9289
9261
|
"args": {
|
|
@@ -9780,6 +9752,34 @@
|
|
|
9780
9752
|
"wait.js"
|
|
9781
9753
|
]
|
|
9782
9754
|
},
|
|
9755
|
+
"teams": {
|
|
9756
|
+
"aliases": [],
|
|
9757
|
+
"args": {},
|
|
9758
|
+
"description": "list the teams that you are a member of\n\nUse heroku members:* to manage team members.",
|
|
9759
|
+
"flags": {
|
|
9760
|
+
"json": {
|
|
9761
|
+
"description": "output in json format",
|
|
9762
|
+
"name": "json",
|
|
9763
|
+
"allowNo": false,
|
|
9764
|
+
"type": "boolean"
|
|
9765
|
+
}
|
|
9766
|
+
},
|
|
9767
|
+
"hasDynamicHelp": false,
|
|
9768
|
+
"hiddenAliases": [],
|
|
9769
|
+
"id": "teams",
|
|
9770
|
+
"pluginAlias": "heroku",
|
|
9771
|
+
"pluginName": "heroku",
|
|
9772
|
+
"pluginType": "core",
|
|
9773
|
+
"strict": true,
|
|
9774
|
+
"topic": "teams",
|
|
9775
|
+
"isESM": false,
|
|
9776
|
+
"relativePath": [
|
|
9777
|
+
"lib",
|
|
9778
|
+
"commands",
|
|
9779
|
+
"teams",
|
|
9780
|
+
"index.js"
|
|
9781
|
+
]
|
|
9782
|
+
},
|
|
9783
9783
|
"webhooks:add": {
|
|
9784
9784
|
"aliases": [],
|
|
9785
9785
|
"args": {},
|
|
@@ -13763,5 +13763,5 @@
|
|
|
13763
13763
|
]
|
|
13764
13764
|
}
|
|
13765
13765
|
},
|
|
13766
|
-
"version": "9.
|
|
13766
|
+
"version": "9.1.0"
|
|
13767
13767
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "heroku",
|
|
3
3
|
"description": "CLI to interact with Heroku",
|
|
4
|
-
"version": "9.
|
|
4
|
+
"version": "9.1.0",
|
|
5
5
|
"author": "Heroku",
|
|
6
6
|
"bin": "./bin/run",
|
|
7
7
|
"bugs": "https://github.com/heroku/cli/issues",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"@heroku/buildpack-registry": "^1.0.1",
|
|
16
16
|
"@heroku/eventsource": "^1.0.7",
|
|
17
17
|
"@heroku/heroku-cli-util": "^8.0.13",
|
|
18
|
+
"@inquirer/prompts": "^5.0.5",
|
|
18
19
|
"@oclif/core": "^2.16.0",
|
|
19
20
|
"@oclif/plugin-commands": "2.2.28",
|
|
20
21
|
"@oclif/plugin-help": "^5",
|
|
@@ -388,5 +389,5 @@
|
|
|
388
389
|
"version": "oclif readme --multi && git add README.md ../../docs"
|
|
389
390
|
},
|
|
390
391
|
"types": "lib/index.d.ts",
|
|
391
|
-
"gitHead": "
|
|
392
|
+
"gitHead": "e1e5252b06e21e3b191025f96a3bd7f139af2098"
|
|
392
393
|
}
|