heroku 10.5.0 → 10.5.1-beta.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/README.md CHANGED
@@ -34,6 +34,7 @@ For other issues, [submit a support ticket](https://help.heroku.com/).
34
34
  # Command Topics
35
35
 
36
36
  * [`heroku access`](docs/access.md) - manage user access to apps
37
+ * [`heroku accounts`](docs/accounts.md) - list the Heroku accounts in your cache
37
38
  * [`heroku addons`](docs/addons.md) - tools and services for developing, extending, and operating your app
38
39
  * [`heroku apps`](docs/apps.md) - manage apps on Heroku
39
40
  * [`heroku auth`](docs/auth.md) - manage authentication for your Heroku account
@@ -73,7 +74,7 @@ For other issues, [submit a support ticket](https://help.heroku.com/).
73
74
  * [`heroku teams`](docs/teams.md) - manage teams
74
75
  * [`heroku telemetry`](docs/telemetry.md) - list telemetry drains
75
76
  * [`heroku update`](docs/update.md) - update the Heroku CLI
76
- * [`heroku usage`](docs/usage.md) - list usage values for metered addons associated with a given app or team
77
+ * [`heroku usage`](docs/usage.md) - list usage for metered add-ons attached to an app or apps within a team
77
78
  * [`heroku version`](docs/version.md)
78
79
  * [`heroku webhooks`](docs/webhooks.md) - list webhooks on an app
79
80
 
@@ -0,0 +1,9 @@
1
+ import { Command } from '@heroku-cli/command';
2
+ export default class Add extends Command {
3
+ static description: string;
4
+ static args: {
5
+ name: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static example: string;
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const command_1 = require("@heroku-cli/command");
4
+ const core_1 = require("@oclif/core");
5
+ const accounts_1 = require("../../lib/accounts/accounts");
6
+ class Add extends command_1.Command {
7
+ async run() {
8
+ const { args } = await this.parse(Add);
9
+ const { name } = args;
10
+ const logInMessage = 'You must be logged in to run this command.';
11
+ if ((0, accounts_1.list)().some(a => a.name === name)) {
12
+ core_1.ux.error(`${name} already exists`);
13
+ }
14
+ const { body: account } = await this.heroku.get('/account');
15
+ const email = account.email || '';
16
+ const token = this.heroku.auth || '';
17
+ if (token === '') {
18
+ core_1.ux.error(logInMessage);
19
+ }
20
+ if (email === '') {
21
+ core_1.ux.error(logInMessage);
22
+ }
23
+ (0, accounts_1.add)(name, email, token);
24
+ }
25
+ }
26
+ exports.default = Add;
27
+ Add.description = 'add a Heroku account to your cache';
28
+ Add.args = {
29
+ name: core_1.Args.string({ description: 'name of Heroku account to add', required: true }),
30
+ };
31
+ Add.example = 'heroku accounts:add my-account';
@@ -0,0 +1,6 @@
1
+ import { Command } from '@heroku-cli/command';
2
+ export default class Current extends Command {
3
+ static description: string;
4
+ static example: string;
5
+ run(): Promise<void>;
6
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const command_1 = require("@heroku-cli/command");
4
+ const core_1 = require("@oclif/core");
5
+ const accounts_1 = require("../../lib/accounts/accounts");
6
+ const color_1 = require("@heroku-cli/color");
7
+ class Current extends command_1.Command {
8
+ async run() {
9
+ const account = (0, accounts_1.current)();
10
+ if (account) {
11
+ core_1.ux.styledHeader(`Current account is ${account}`);
12
+ }
13
+ else {
14
+ core_1.ux.error(`You haven't set an account. Run ${color_1.default.cmd('heroku accounts:add <account-name>')} to add an account to your cache or ${color_1.default.cmd('heroku accounts:set <account-name>')} to set the current account.`);
15
+ }
16
+ }
17
+ }
18
+ exports.default = Current;
19
+ Current.description = 'display the current Heroku account';
20
+ Current.example = 'heroku accounts:current';
@@ -0,0 +1,6 @@
1
+ import { Command } from '@heroku-cli/command';
2
+ export default class AccountsIndex extends Command {
3
+ static description: string;
4
+ static example: string;
5
+ run(): Promise<void>;
6
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const command_1 = require("@heroku-cli/command");
4
+ const core_1 = require("@oclif/core");
5
+ const accounts_1 = require("../../lib/accounts/accounts");
6
+ class AccountsIndex extends command_1.Command {
7
+ async run() {
8
+ const accounts = (0, accounts_1.list)();
9
+ if (accounts.length === 0) {
10
+ core_1.ux.error('You don\'t have any accounts in your cache.');
11
+ }
12
+ for (const account of accounts) {
13
+ if (account.name === (0, accounts_1.current)()) {
14
+ core_1.ux.log(`* ${account.name}`);
15
+ }
16
+ else {
17
+ core_1.ux.log(` ${account.name}`);
18
+ }
19
+ }
20
+ }
21
+ }
22
+ exports.default = AccountsIndex;
23
+ AccountsIndex.description = 'list the Heroku accounts in your cache';
24
+ AccountsIndex.example = 'heroku accounts';
@@ -0,0 +1,9 @@
1
+ import { Command } from '@heroku-cli/command';
2
+ export default class Remove extends Command {
3
+ static description: string;
4
+ static args: {
5
+ name: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static example: string;
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const command_1 = require("@heroku-cli/command");
4
+ const core_1 = require("@oclif/core");
5
+ const accounts_1 = require("../../lib/accounts/accounts");
6
+ class Remove extends command_1.Command {
7
+ async run() {
8
+ const { args } = await this.parse(Remove);
9
+ const { name } = args;
10
+ if (!(0, accounts_1.list)().some(a => a.name === name)) {
11
+ core_1.ux.error(`${name} doesn't exist in your accounts cache.`);
12
+ }
13
+ if ((0, accounts_1.current)() === name) {
14
+ core_1.ux.error(`${name} is the current account.`);
15
+ }
16
+ (0, accounts_1.remove)(name);
17
+ }
18
+ }
19
+ exports.default = Remove;
20
+ Remove.description = 'remove a Heroku account from your cache';
21
+ Remove.args = {
22
+ name: core_1.Args.string({ description: 'name of Heroku account to remove', required: true }),
23
+ };
24
+ Remove.example = 'heroku accounts:remove my-account';
@@ -0,0 +1,9 @@
1
+ import { Command } from '@heroku-cli/command';
2
+ export default class Set extends Command {
3
+ static description: string;
4
+ static args: {
5
+ name: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static example: string;
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const command_1 = require("@heroku-cli/command");
4
+ const core_1 = require("@oclif/core");
5
+ const accounts_1 = require("../../lib/accounts/accounts");
6
+ class Set extends command_1.Command {
7
+ async run() {
8
+ const { args } = await this.parse(Set);
9
+ const { name } = args;
10
+ if (!(0, accounts_1.list)().some(a => a.name === name)) {
11
+ core_1.ux.error(`${name} does not exist in your accounts cache.`);
12
+ }
13
+ (0, accounts_1.set)(name);
14
+ }
15
+ }
16
+ exports.default = Set;
17
+ Set.description = 'set the current Heroku account from your cache';
18
+ Set.args = {
19
+ name: core_1.Args.string({ description: 'name of account to set', required: true }),
20
+ };
21
+ Set.example = 'heroku accounts:set my-account';
@@ -22,6 +22,35 @@ const COST_MONTHLY = {
22
22
  'Performance-L-RAM': 500,
23
23
  'Performance-XL': 750,
24
24
  'Performance-2XL': 1500,
25
+ 'Private-S': 225,
26
+ 'Private-M': 450,
27
+ 'Private-L': 900,
28
+ 'Shield-M': 540,
29
+ 'Shield-L': 1080,
30
+ 'Shield-S': 270,
31
+ 'Private-Memory-L': 500,
32
+ 'Private-Memory-XL': 750,
33
+ 'Private-Memory-2XL': 1500,
34
+ 'Shield-Memory-L': 600,
35
+ 'Shield-Memory-XL': 900,
36
+ 'Shield-Memory-2XL': 1800,
37
+ 'dyno-1c-0.5gb': 25,
38
+ 'dyno-2c-1gb': 50,
39
+ 'dyno-1c-4gb': 80,
40
+ 'dyno-2c-8gb': 160,
41
+ 'dyno-4c-16gb': 320,
42
+ 'dyno-8c-32gb': 640,
43
+ 'dyno-16c-64gb': 1000,
44
+ 'dyno-2c-4gb': 150,
45
+ 'dyno-4c-8gb': 300,
46
+ 'dyno-8c-16gb': 600,
47
+ 'dyno-16c-32gb': 1200,
48
+ 'dyno-32c-64gb': 2400,
49
+ 'dyno-1c-8gb': 100,
50
+ 'dyno-2c-16gb': 250,
51
+ 'dyno-4c-32gb': 500,
52
+ 'dyno-8c-64gb': 750,
53
+ 'dyno-16c-128gb': 1500,
25
54
  };
26
55
  const calculateHourly = (size) => COST_MONTHLY[size] / 720;
27
56
  const emptyFormationErr = (app) => {
@@ -12,7 +12,7 @@ class UsageAddons extends command_1.Command {
12
12
  })));
13
13
  core_1.ux.styledHeader(`Usage for ${color_1.default.app(app)}`);
14
14
  core_1.ux.table(metersArray, {
15
- Addon: {
15
+ 'Add-on': {
16
16
  get: row => {
17
17
  const matchingAddon = appAddons.find(a => a.id === row.addonId);
18
18
  return (matchingAddon === null || matchingAddon === void 0 ? void 0 : matchingAddon.name) || row.addonId;
@@ -111,8 +111,8 @@ class UsageAddons extends command_1.Command {
111
111
  }
112
112
  exports.default = UsageAddons;
113
113
  UsageAddons.topic = 'usage';
114
- UsageAddons.description = 'list usage values for metered addons associated with a given app or team';
114
+ UsageAddons.description = 'list usage for metered add-ons attached to an app or apps within a team';
115
115
  UsageAddons.flags = {
116
- app: command_1.flags.string(),
117
- team: command_1.flags.string(),
116
+ app: command_1.flags.string({ char: 'a', description: 'app to list metered add-ons usage for' }),
117
+ team: command_1.flags.team({ description: 'team to list metered add-ons usage for' }),
118
118
  };
@@ -0,0 +1,6 @@
1
+ import * as Heroku from '@heroku-cli/schema';
2
+ export declare function list(): Heroku.Account[] | [];
3
+ export declare function current(): string | null;
4
+ export declare function add(name: string, username: string, password: string): void;
5
+ export declare function remove(name: string): void;
6
+ export declare function set(name: string): void;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.set = exports.remove = exports.add = exports.current = exports.list = void 0;
4
+ const yaml_1 = require("yaml");
5
+ const fs = require("fs");
6
+ const os = require("node:os");
7
+ const path = require("node:path");
8
+ const netrc_parser_1 = require("netrc-parser");
9
+ function configDir() {
10
+ const legacyDir = path.join(os.homedir(), '.heroku');
11
+ if (fs.existsSync(legacyDir)) {
12
+ return legacyDir;
13
+ }
14
+ return path.join(os.homedir(), '.config', 'heroku');
15
+ }
16
+ function account(name) {
17
+ const basedir = path.join(configDir(), 'accounts');
18
+ const file = fs.readFileSync(path.join(basedir, name), 'utf8');
19
+ const account = (0, yaml_1.parse)(file);
20
+ if (account[':username']) {
21
+ // convert from ruby symbols
22
+ account.username = account[':username'];
23
+ account.password = account[':password'];
24
+ delete account[':username'];
25
+ delete account[':password'];
26
+ }
27
+ return account;
28
+ }
29
+ function list() {
30
+ const basedir = path.join(configDir(), 'accounts');
31
+ try {
32
+ return fs.readdirSync(basedir)
33
+ .map(name => Object.assign(account(name), { name }));
34
+ }
35
+ catch (_a) {
36
+ return [];
37
+ }
38
+ }
39
+ exports.list = list;
40
+ function current() {
41
+ if (netrc_parser_1.default.machines['api.heroku.com']) {
42
+ const current = list().find(a => a.username === netrc_parser_1.default.machines['api.heroku.com'].login);
43
+ return current && current.name ? current.name : null;
44
+ }
45
+ return null;
46
+ }
47
+ exports.current = current;
48
+ function add(name, username, password) {
49
+ const basedir = path.join(configDir(), 'accounts');
50
+ fs.mkdirSync(basedir, { recursive: true });
51
+ fs.writeFileSync(path.join(basedir, name), (0, yaml_1.stringify)({ username, password }), 'utf8');
52
+ fs.chmodSync(path.join(basedir, name), 0o600);
53
+ }
54
+ exports.add = add;
55
+ function remove(name) {
56
+ const basedir = path.join(configDir(), 'accounts');
57
+ fs.unlinkSync(path.join(basedir, name));
58
+ }
59
+ exports.remove = remove;
60
+ function set(name) {
61
+ const current = account(name);
62
+ netrc_parser_1.default.machines['git.heroku.com'] = {};
63
+ netrc_parser_1.default.machines['api.heroku.com'] = {};
64
+ netrc_parser_1.default.machines['git.heroku.com'].login = current.username;
65
+ netrc_parser_1.default.machines['api.heroku.com'].login = current.username;
66
+ netrc_parser_1.default.machines['git.heroku.com'].password = current.password;
67
+ netrc_parser_1.default.machines['api.heroku.com'].password = current.password;
68
+ netrc_parser_1.default.saveSync();
69
+ }
70
+ exports.set = set;
@@ -533,6 +533,134 @@
533
533
  "update.js"
534
534
  ]
535
535
  },
536
+ "accounts:add": {
537
+ "aliases": [],
538
+ "args": {
539
+ "name": {
540
+ "description": "name of Heroku account to add",
541
+ "name": "name",
542
+ "required": true
543
+ }
544
+ },
545
+ "description": "add a Heroku account to your cache",
546
+ "examples": "heroku accounts:add my-account",
547
+ "flags": {},
548
+ "hasDynamicHelp": false,
549
+ "hiddenAliases": [],
550
+ "id": "accounts:add",
551
+ "pluginAlias": "heroku",
552
+ "pluginName": "heroku",
553
+ "pluginType": "core",
554
+ "strict": true,
555
+ "example": "heroku accounts:add my-account",
556
+ "isESM": false,
557
+ "relativePath": [
558
+ "lib",
559
+ "commands",
560
+ "accounts",
561
+ "add.js"
562
+ ]
563
+ },
564
+ "accounts:current": {
565
+ "aliases": [],
566
+ "args": {},
567
+ "description": "display the current Heroku account",
568
+ "examples": "heroku accounts:current",
569
+ "flags": {},
570
+ "hasDynamicHelp": false,
571
+ "hiddenAliases": [],
572
+ "id": "accounts:current",
573
+ "pluginAlias": "heroku",
574
+ "pluginName": "heroku",
575
+ "pluginType": "core",
576
+ "strict": true,
577
+ "example": "heroku accounts:current",
578
+ "isESM": false,
579
+ "relativePath": [
580
+ "lib",
581
+ "commands",
582
+ "accounts",
583
+ "current.js"
584
+ ]
585
+ },
586
+ "accounts": {
587
+ "aliases": [],
588
+ "args": {},
589
+ "description": "list the Heroku accounts in your cache",
590
+ "examples": "heroku accounts",
591
+ "flags": {},
592
+ "hasDynamicHelp": false,
593
+ "hiddenAliases": [],
594
+ "id": "accounts",
595
+ "pluginAlias": "heroku",
596
+ "pluginName": "heroku",
597
+ "pluginType": "core",
598
+ "strict": true,
599
+ "example": "heroku accounts",
600
+ "isESM": false,
601
+ "relativePath": [
602
+ "lib",
603
+ "commands",
604
+ "accounts",
605
+ "index.js"
606
+ ]
607
+ },
608
+ "accounts:remove": {
609
+ "aliases": [],
610
+ "args": {
611
+ "name": {
612
+ "description": "name of Heroku account to remove",
613
+ "name": "name",
614
+ "required": true
615
+ }
616
+ },
617
+ "description": "remove a Heroku account from your cache",
618
+ "examples": "heroku accounts:remove my-account",
619
+ "flags": {},
620
+ "hasDynamicHelp": false,
621
+ "hiddenAliases": [],
622
+ "id": "accounts:remove",
623
+ "pluginAlias": "heroku",
624
+ "pluginName": "heroku",
625
+ "pluginType": "core",
626
+ "strict": true,
627
+ "example": "heroku accounts:remove my-account",
628
+ "isESM": false,
629
+ "relativePath": [
630
+ "lib",
631
+ "commands",
632
+ "accounts",
633
+ "remove.js"
634
+ ]
635
+ },
636
+ "accounts:set": {
637
+ "aliases": [],
638
+ "args": {
639
+ "name": {
640
+ "description": "name of account to set",
641
+ "name": "name",
642
+ "required": true
643
+ }
644
+ },
645
+ "description": "set the current Heroku account from your cache",
646
+ "examples": "heroku accounts:set my-account",
647
+ "flags": {},
648
+ "hasDynamicHelp": false,
649
+ "hiddenAliases": [],
650
+ "id": "accounts:set",
651
+ "pluginAlias": "heroku",
652
+ "pluginName": "heroku",
653
+ "pluginType": "core",
654
+ "strict": true,
655
+ "example": "heroku accounts:set my-account",
656
+ "isESM": false,
657
+ "relativePath": [
658
+ "lib",
659
+ "commands",
660
+ "accounts",
661
+ "set.js"
662
+ ]
663
+ },
536
664
  "addons:attach": {
537
665
  "aliases": [],
538
666
  "args": {
@@ -10275,15 +10403,19 @@
10275
10403
  "usage:addons": {
10276
10404
  "aliases": [],
10277
10405
  "args": {},
10278
- "description": "list usage values for metered addons associated with a given app or team",
10406
+ "description": "list usage for metered add-ons attached to an app or apps within a team",
10279
10407
  "flags": {
10280
10408
  "app": {
10409
+ "char": "a",
10410
+ "description": "app to list metered add-ons usage for",
10281
10411
  "name": "app",
10282
10412
  "hasDynamicHelp": false,
10283
10413
  "multiple": false,
10284
10414
  "type": "option"
10285
10415
  },
10286
10416
  "team": {
10417
+ "char": "t",
10418
+ "description": "team to list metered add-ons usage for",
10287
10419
  "name": "team",
10288
10420
  "hasDynamicHelp": false,
10289
10421
  "multiple": false,
@@ -14520,5 +14652,5 @@
14520
14652
  ]
14521
14653
  }
14522
14654
  },
14523
- "version": "10.5.0"
14655
+ "version": "10.5.1-beta.0"
14524
14656
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "heroku",
3
3
  "description": "CLI to interact with Heroku",
4
- "version": "10.5.0",
4
+ "version": "10.5.1-beta.0",
5
5
  "author": "Heroku",
6
6
  "bin": "./bin/run",
7
7
  "bugs": "https://github.com/heroku/cli/issues",
@@ -78,7 +78,8 @@
78
78
  "urijs": "^1.19.11",
79
79
  "validator": "^13.7.0",
80
80
  "word-wrap": "^1.2.5",
81
- "ws": "^6.2.2"
81
+ "ws": "^6.2.2",
82
+ "yaml": "^2.0.1"
82
83
  },
83
84
  "devDependencies": {
84
85
  "@heroku-cli/schema": "^1.0.25",
@@ -397,5 +398,5 @@
397
398
  "version": "oclif readme --multi && git add README.md ../../docs"
398
399
  },
399
400
  "types": "lib/index.d.ts",
400
- "gitHead": "508b163af7ae9a143cae0f02589b50b4a0a81d50"
401
+ "gitHead": "65bb66c86fd0c948e3d0971737c1032ac99be819"
401
402
  }