@heroku/heroku-cli-util 9.0.0-beta.2 → 9.0.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
@@ -19,50 +19,97 @@ npm install @heroku/heroku-cli-util
19
19
 
20
20
  ## Usage
21
21
 
22
- You can import the utilities you need.
22
+ You can import the utilities you need from the main exports.
23
23
 
24
24
  ### Output Utilities
25
25
 
26
26
  ```js
27
+ import { hux } from '@heroku/heroku-cli-util';
28
+
27
29
  // Styled header
28
- import { styledHeader } from '@heroku/heroku-cli-util/dist/ux/styled-header';
29
- styledHeader('My CLI Header');
30
+ hux.styledHeader('My CLI Header');
30
31
 
31
32
  // Styled JSON
32
- import { styledJSON } from '@heroku/heroku-cli-util/dist/ux/styled-json';
33
- styledJSON({ foo: 'bar' });
33
+ hux.styledJson({ foo: 'bar' });
34
34
 
35
35
  // Styled object
36
- import { styledObject } from '@heroku/heroku-cli-util/dist/ux/styled-object';
37
- styledObject({ foo: 'bar' });
38
-
39
- // Table
40
- import { table } from '@heroku/heroku-cli-util/dist/ux/table';
41
- table([{ name: 'Alice' }, { name: 'Bob' }], { columns: [{ key: 'name' }] });
42
-
43
- // Wait
44
- import { wait } from '@heroku/heroku-cli-util/dist/ux/wait';
45
- await wait('Processing...');
36
+ hux.styledObject({ foo: 'bar' });
46
37
  ```
47
38
 
48
39
  ### User Interaction
49
40
 
50
41
  ```js
51
- import { prompt } from '@heroku/heroku-cli-util/dist/ux/prompt';
52
- const name = await prompt('What is your name?');
42
+ import { hux } from '@heroku/heroku-cli-util';
53
43
 
54
- import { confirm } from '@heroku/heroku-cli-util/dist/ux/confirm';
55
- const proceed = await confirm('Continue?');
44
+ const name = await hux.prompt('What is your name?');
45
+ const proceed = await hux.confirm('Continue?');
56
46
  ```
57
47
 
58
48
  ### Test Helpers
59
49
 
60
50
  ```js
61
- import { initCliTest } from '@heroku/heroku-cli-util/dist/test-helpers/init';
62
- initCliTest();
51
+ import { testHelpers } from '@heroku/heroku-cli-util';
52
+
53
+ testHelpers.initCliTest();
54
+
55
+ testHelpers.setupStdoutStderr();
56
+ // ...run your CLI code...
57
+ const output = testHelpers.stdout();
58
+ const errorOutput = testHelpers.stderr();
59
+ testHelpers.restoreStdoutStderr();
60
+
61
+ testHelpers.expectOutput(output, 'expected output');
62
+
63
+ // Run a command (see docs for details)
64
+ // await testHelpers.runCommand(MyCommand, ['arg1', 'arg2']);
65
+ ```
66
+
67
+ ### Types
68
+
69
+ ```js
70
+ import { types } from '@heroku/heroku-cli-util';
71
+
72
+ // Error types
73
+ try {
74
+ throw new types.errors.AmbiguousError([{ name: 'foo' }, { name: 'bar' }], 'addon');
75
+ } catch (err) {
76
+ if (err instanceof types.errors.AmbiguousError) {
77
+ console.error('Ambiguous:', err.message);
78
+ }
79
+ }
80
+
81
+ try {
82
+ throw new types.errors.NotFound();
83
+ } catch (err) {
84
+ if (err instanceof types.errors.NotFound) {
85
+ console.error('Not found:', err.message);
86
+ }
87
+ }
88
+
89
+ // PG types (for TypeScript)
90
+ /**
91
+ * types.pg.AddOnAttachmentWithConfigVarsAndPlan
92
+ * types.pg.AddOnWithRelatedData
93
+ * types.pg.ConnectionDetails
94
+ * types.pg.ConnectionDetailsWithAttachment
95
+ * types.pg.Link
96
+ * types.pg.TunnelConfig
97
+ */
98
+ ```
99
+
100
+ ### Database and Utility Helpers
101
+
102
+ ```js
103
+ import { utils } from '@heroku/heroku-cli-util';
104
+
105
+ // Get Heroku Postgres database connection details (requires APIClient from @heroku-cli/command)
106
+ // const db = await utils.pg.databases(herokuApiClient, 'my-app', 'DATABASE_URL');
107
+
108
+ // Get Heroku Postgres host
109
+ const host = utils.pg.host();
63
110
 
64
- import { stdout, stderr } from '@heroku/heroku-cli-util/dist/test-helpers/stub-output';
65
- // Use stdout() and stderr() in your tests to capture CLI output
111
+ // Run a query (requires a ConnectionDetails object)
112
+ // const result = await utils.pg.psql.exec(db, 'SELECT 1');
66
113
  ```
67
114
 
68
115
  ## Development
package/dist/index.d.ts CHANGED
@@ -1,28 +1,53 @@
1
1
  import { initCliTest } from './test-helpers/init';
2
2
  import { restoreStdoutStderr, setupStdoutStderr, stderr, stdout } from './test-helpers/stub-output';
3
+ import { AmbiguousError } from './types/errors/ambiguous';
4
+ import { NotFound } from './types/errors/not-found';
5
+ import { AddOnAttachmentWithConfigVarsAndPlan, AddOnWithRelatedData, Link } from './types/pg/data-api';
6
+ import { ConnectionDetails, ConnectionDetailsWithAttachment, TunnelConfig } from './types/pg/tunnel';
7
+ import { getDatabase } from './utils/pg/databases';
8
+ import getHost from './utils/pg/host';
9
+ import { exec } from './utils/pg/psql';
10
+ import { confirm } from './ux/confirm';
11
+ import { prompt } from './ux/prompt';
12
+ import { styledHeader } from './ux/styled-header';
13
+ import { styledJson } from './ux/styled-json';
14
+ import { styledObject } from './ux/styled-object';
3
15
  export declare const testHelpers: {
4
16
  expectOutput: (actual: string, expected: string) => Chai.Assertion;
5
17
  initCliTest: typeof initCliTest;
6
18
  restoreStdoutStderr: typeof restoreStdoutStderr;
19
+ runCommand: (Cmd: import("./test-helpers/run-command").GenericCmd, args?: string[], printStd?: boolean) => Promise<any>;
7
20
  setupStdoutStderr: typeof setupStdoutStderr;
8
21
  stderr: typeof stderr;
9
22
  stdout: typeof stdout;
10
23
  };
11
- export { default as expectOutput } from './test-helpers/expect-output';
12
- export * from './types/errors/ambiguous';
13
- export * from './types/errors/not-found';
14
- export * from './types/pg/data-api';
15
- export * from './types/pg/tunnel';
16
- export * from './utils/addons/resolve';
17
- export * from './utils/pg/bastion';
18
- export * from './utils/pg/config-vars';
19
- export * from './utils/pg/databases';
20
- export { default as getPgHost } from './utils/pg/host';
21
- export * from './utils/pg/psql';
22
- export * from './ux/confirm';
23
- export * from './ux/prompt';
24
- export * from './ux/styled-header';
25
- export * from './ux/styled-json';
26
- export * from './ux/styled-object';
27
- export * from './ux/table';
28
- export * from './ux/wait';
24
+ export declare const types: {
25
+ errors: {
26
+ AmbiguousError: typeof AmbiguousError;
27
+ NotFound: typeof NotFound;
28
+ };
29
+ pg: {
30
+ AddOnAttachmentWithConfigVarsAndPlan: AddOnAttachmentWithConfigVarsAndPlan;
31
+ AddOnWithRelatedData: AddOnWithRelatedData;
32
+ ConnectionDetails: ConnectionDetails;
33
+ ConnectionDetailsWithAttachment: ConnectionDetailsWithAttachment;
34
+ Link: Link;
35
+ TunnelConfig: TunnelConfig;
36
+ };
37
+ };
38
+ export declare const utils: {
39
+ pg: {
40
+ databases: typeof getDatabase;
41
+ host: typeof getHost;
42
+ psql: {
43
+ exec: typeof exec;
44
+ };
45
+ };
46
+ };
47
+ export declare const hux: {
48
+ confirm: typeof confirm;
49
+ prompt: typeof prompt;
50
+ styledHeader: typeof styledHeader;
51
+ styledJson: typeof styledJson;
52
+ styledObject: typeof styledObject;
53
+ };
package/dist/index.js CHANGED
@@ -1,40 +1,56 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getPgHost = exports.expectOutput = exports.testHelpers = void 0;
4
- const tslib_1 = require("tslib");
5
- // Test helpers (optional, for test environments)
3
+ exports.hux = exports.utils = exports.types = exports.testHelpers = void 0;
6
4
  const expect_output_1 = require("./test-helpers/expect-output");
7
5
  const init_1 = require("./test-helpers/init");
6
+ const run_command_1 = require("./test-helpers/run-command");
8
7
  const stub_output_1 = require("./test-helpers/stub-output");
8
+ const ambiguous_1 = require("./types/errors/ambiguous");
9
+ const not_found_1 = require("./types/errors/not-found");
10
+ const databases_1 = require("./utils/pg/databases");
11
+ const host_1 = require("./utils/pg/host");
12
+ const psql_1 = require("./utils/pg/psql");
13
+ const confirm_1 = require("./ux/confirm");
14
+ const prompt_1 = require("./ux/prompt");
15
+ const styled_header_1 = require("./ux/styled-header");
16
+ const styled_json_1 = require("./ux/styled-json");
17
+ const styled_object_1 = require("./ux/styled-object");
9
18
  exports.testHelpers = {
10
19
  expectOutput: expect_output_1.default,
11
20
  initCliTest: init_1.initCliTest,
12
21
  restoreStdoutStderr: stub_output_1.restoreStdoutStderr,
22
+ runCommand: run_command_1.runCommand,
13
23
  setupStdoutStderr: stub_output_1.setupStdoutStderr,
14
24
  stderr: stub_output_1.stderr,
15
25
  stdout: stub_output_1.stdout,
16
26
  };
17
- var expect_output_2 = require("./test-helpers/expect-output");
18
- Object.defineProperty(exports, "expectOutput", { enumerable: true, get: function () { return expect_output_2.default; } });
19
- // Types - Errors
20
- tslib_1.__exportStar(require("./types/errors/ambiguous"), exports);
21
- tslib_1.__exportStar(require("./types/errors/not-found"), exports);
22
- // Types - PG
23
- tslib_1.__exportStar(require("./types/pg/data-api"), exports);
24
- tslib_1.__exportStar(require("./types/pg/tunnel"), exports);
25
- tslib_1.__exportStar(require("./utils/addons/resolve"), exports);
26
- // Utilities - Postgres
27
- tslib_1.__exportStar(require("./utils/pg/bastion"), exports);
28
- tslib_1.__exportStar(require("./utils/pg/config-vars"), exports);
29
- tslib_1.__exportStar(require("./utils/pg/databases"), exports);
30
- var host_1 = require("./utils/pg/host");
31
- Object.defineProperty(exports, "getPgHost", { enumerable: true, get: function () { return host_1.default; } });
32
- tslib_1.__exportStar(require("./utils/pg/psql"), exports);
33
- // UX helpers
34
- tslib_1.__exportStar(require("./ux/confirm"), exports);
35
- tslib_1.__exportStar(require("./ux/prompt"), exports);
36
- tslib_1.__exportStar(require("./ux/styled-header"), exports);
37
- tslib_1.__exportStar(require("./ux/styled-json"), exports);
38
- tslib_1.__exportStar(require("./ux/styled-object"), exports);
39
- tslib_1.__exportStar(require("./ux/table"), exports);
40
- tslib_1.__exportStar(require("./ux/wait"), exports);
27
+ exports.types = {
28
+ errors: {
29
+ AmbiguousError: ambiguous_1.AmbiguousError,
30
+ NotFound: not_found_1.NotFound,
31
+ },
32
+ pg: {
33
+ AddOnAttachmentWithConfigVarsAndPlan: {},
34
+ AddOnWithRelatedData: {},
35
+ ConnectionDetails: {},
36
+ ConnectionDetailsWithAttachment: {},
37
+ Link: {},
38
+ TunnelConfig: {},
39
+ },
40
+ };
41
+ exports.utils = {
42
+ pg: {
43
+ databases: databases_1.getDatabase,
44
+ host: host_1.default,
45
+ psql: {
46
+ exec: psql_1.exec,
47
+ },
48
+ },
49
+ };
50
+ exports.hux = {
51
+ confirm: confirm_1.confirm,
52
+ prompt: prompt_1.prompt,
53
+ styledHeader: styled_header_1.styledHeader,
54
+ styledJson: styled_json_1.styledJson,
55
+ styledObject: styled_object_1.styledObject,
56
+ };
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.initCliTest = initCliTest;
4
4
  const path = require('node:path');
5
- // eslint-disable-next-line n/no-missing-require
6
5
  const { color } = require('@heroku-cli/color');
7
6
  const nock = require('nock');
8
7
  function initCliTest() {
@@ -0,0 +1,9 @@
1
+ import { Command } from '@heroku-cli/command';
2
+ import { APIClient } from '@heroku-cli/command';
3
+ import { Config } from '@oclif/core';
4
+ type CmdConstructorParams = ConstructorParameters<typeof Command>;
5
+ export type GenericCmd = new (...args: CmdConstructorParams) => Command;
6
+ export declare const runCommand: (Cmd: GenericCmd, args?: string[], printStd?: boolean) => Promise<any>;
7
+ export declare const getConfig: () => Promise<Config>;
8
+ export declare const getHerokuAPI: () => Promise<APIClient>;
9
+ export {};
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getHerokuAPI = exports.getConfig = exports.runCommand = void 0;
4
+ const command_1 = require("@heroku-cli/command");
5
+ const core_1 = require("@oclif/core");
6
+ const stdout_stderr_1 = require("stdout-stderr");
7
+ const stopMock = () => {
8
+ stdout_stderr_1.stdout.stop();
9
+ stdout_stderr_1.stderr.stop();
10
+ };
11
+ const runCommand = async (Cmd, args = [], printStd = false) => {
12
+ const conf = await (0, exports.getConfig)();
13
+ const instance = new Cmd(args, conf);
14
+ if (printStd) {
15
+ stdout_stderr_1.stdout.print = true;
16
+ stdout_stderr_1.stderr.print = true;
17
+ }
18
+ stdout_stderr_1.stdout.start();
19
+ stdout_stderr_1.stderr.start();
20
+ return instance
21
+ .run()
22
+ .then(args => {
23
+ stopMock();
24
+ return args;
25
+ })
26
+ .catch((error) => {
27
+ stopMock();
28
+ throw error;
29
+ });
30
+ };
31
+ exports.runCommand = runCommand;
32
+ const getConfig = async () => {
33
+ const pjsonPath = require.resolve('../../package.json');
34
+ const conf = new core_1.Config({ root: pjsonPath });
35
+ await conf.load();
36
+ return conf;
37
+ };
38
+ exports.getConfig = getConfig;
39
+ const getHerokuAPI = async () => {
40
+ const conf = await (0, exports.getConfig)();
41
+ return new command_1.APIClient(conf);
42
+ };
43
+ exports.getHerokuAPI = getHerokuAPI;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "commonjs",
3
3
  "name": "@heroku/heroku-cli-util",
4
- "version": "9.0.0-beta.2",
4
+ "version": "9.0.0",
5
5
  "description": "Set of helpful CLI utilities",
6
6
  "author": "Heroku",
7
7
  "license": "ISC",
@@ -13,12 +13,14 @@
13
13
  "devDependencies": {
14
14
  "@heroku-cli/schema": "^2.0.0",
15
15
  "@types/chai": "^4.3.13",
16
+ "@types/chai-as-promised": "^8.0.2",
16
17
  "@types/debug": "^4.1.12",
17
18
  "@types/mocha": "^10.0.10",
18
19
  "@types/node": "^22.15.3",
19
20
  "@types/sinon": "^17.0.4",
20
21
  "@types/tunnel-ssh": "4.1.1",
21
22
  "chai": "^4.4.1",
23
+ "chai-as-promised": "^8.0.1",
22
24
  "eslint": "^8.57.0",
23
25
  "eslint-config-oclif": "^5.0.0",
24
26
  "eslint-config-oclif-typescript": "^3.1.14",
@@ -34,12 +36,13 @@
34
36
  "typescript": "^5.4.0"
35
37
  },
36
38
  "dependencies": {
37
- "@oclif/core": "^2.16.0",
38
- "@heroku/http-call": "^5.4.0",
39
39
  "@heroku-cli/color": "^2.0.4",
40
40
  "@heroku-cli/command": "^11.5.0",
41
+ "@heroku/http-call": "^5.4.0",
42
+ "@oclif/core": "^2.16.0",
41
43
  "debug": "^4.4.0",
42
44
  "nock": "^13.2.9",
45
+ "stdout-stderr": "^0.1.13",
43
46
  "tunnel-ssh": "4.1.6"
44
47
  },
45
48
  "engines": {
@@ -48,7 +51,8 @@
48
51
  "mocha": {
49
52
  "require": [
50
53
  "ts-node/register",
51
- "source-map-support/register"
54
+ "source-map-support/register",
55
+ "test/hooks.ts"
52
56
  ],
53
57
  "file": [
54
58
  "src/test-helpers/stub-output.ts"
@@ -59,10 +63,10 @@
59
63
  "timeout": 360000
60
64
  },
61
65
  "scripts": {
62
- "build": "tsc",
66
+ "build": "npm run clean && tsc",
63
67
  "clean": "rm -rf dist",
64
68
  "lint": "eslint . --ext .ts --config .eslintrc.js",
65
- "prepare": "npm run clean && npm run build",
69
+ "prepare": "npm run build",
66
70
  "test": "nyc mocha --forbid-only \"test/**/*.test.ts\"",
67
71
  "test:local": "mocha \"test/**/*.test.ts\""
68
72
  }