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.
@@ -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/retrive options from cache
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 falsey
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 { body: domains } = await this.heroku.get(`/apps/${flags.app}/domains`);
51
- const herokuDomain = domains.find(domain => domain.kind === 'heroku');
52
- const customDomains = domains.filter(domain => domain.kind === 'custom');
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 DVCs codebase
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, _c;
17
- if (((_a = app.stack) === null || _a === void 0 ? void 0 : _a.name) !== 'container') {
18
- const appLabel = (((_b = app.stack) === null || _b === void 0 ? void 0 : _b.name) && stackLabelMap[app.stack.name]) || ((_c = app.stack) === null || _c === void 0 ? void 0 : _c.name);
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 += ` Run ${color_1.default.cyan('git push heroku main')} to deploy your ${color_1.default.cyan(app.name)} ${color_1.default.cyan(appLabel)} app instead.`;
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
  }
@@ -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,4 @@
1
+ export default function parseKeyValue(input: string): {
2
+ key: string;
3
+ value: string;
4
+ };
@@ -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,2 @@
1
+ import { APIClient } from '@heroku-cli/command';
2
+ export declare function paginateRequest<T = unknown>(client: APIClient, url: string, pageSize?: number): Promise<T[]>;
@@ -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;
@@ -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.0.0"
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.0.0",
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": "4da724b8d060066189be5d0979a449b65a3e78ff"
392
+ "gitHead": "e1e5252b06e21e3b191025f96a3bd7f139af2098"
392
393
  }