@heroku/heroku-cli-util 10.6.1 → 10.7.0-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
@@ -19,24 +19,38 @@ npm install @heroku/heroku-cli-util
19
19
 
20
20
  ## Usage
21
21
 
22
- You can import the utilities you need from the main exports.
22
+ Import only the utilities you need for better performance and smaller bundle sizes.
23
+
24
+ ```js
25
+ import * as color from '@heroku/heroku-cli-util/color';
26
+ import { confirm, table } from '@heroku/heroku-cli-util/hux';
27
+ import { DatabaseResolver } from '@heroku/heroku-cli-util/utils/pg';
28
+ import { AddonResolver } from '@heroku/heroku-cli-util/utils/addons';
29
+ ```
30
+
31
+ **Available import paths:**
32
+ - `@heroku/heroku-cli-util/color` - Color utilities
33
+ - `@heroku/heroku-cli-util/hux` - UX utilities (prompts, tables, output formatting)
34
+ - `@heroku/heroku-cli-util/utils` - All utility functions
35
+ - `@heroku/heroku-cli-util/utils/pg` - PostgreSQL-specific utilities
36
+ - `@heroku/heroku-cli-util/utils/addons` - Addon-specific utilities
23
37
 
24
38
  ### Output Utilities
25
39
 
26
40
  ```js
27
- import { hux } from '@heroku/heroku-cli-util';
41
+ import { styledHeader, styledJSON, styledObject, table, wait } from '@heroku/heroku-cli-util/hux';
28
42
 
29
43
  // Styled header
30
- hux.styledHeader('My CLI Header');
44
+ styledHeader('My CLI Header');
31
45
 
32
46
  // Styled JSON
33
- hux.styledJSON({ foo: 'bar' });
47
+ styledJSON({ foo: 'bar' });
34
48
 
35
49
  // Styled object
36
- hux.styledObject({ foo: 'bar' });
50
+ styledObject({ foo: 'bar' });
37
51
 
38
52
  // Table output
39
- hux.table([
53
+ table([
40
54
  {name: 'Alice', age: 30},
41
55
  {name: 'Bob', age: 25},
42
56
  ], {
@@ -45,7 +59,7 @@ hux.table([
45
59
  });
46
60
 
47
61
  // Wait indicator
48
- const stop = hux.wait('Processing...');
62
+ const stop = wait('Processing...');
49
63
  // ...do async work...
50
64
  stop();
51
65
  ```
@@ -53,16 +67,16 @@ stop();
53
67
  ### User Interaction
54
68
 
55
69
  ```js
56
- import { hux } from '@heroku/heroku-cli-util';
70
+ import { prompt, confirm } from '@heroku/heroku-cli-util/hux';
57
71
 
58
- const name = await hux.prompt('What is your name?');
59
- const proceed = await hux.confirm('Continue?');
72
+ const name = await prompt('What is your name?');
73
+ const proceed = await confirm('Continue?');
60
74
  ```
61
75
 
62
76
  ### Colors
63
77
 
64
78
  ```js
65
- import { color } from '@heroku/heroku-cli-util';
79
+ import * as color from '@heroku/heroku-cli-util/color';
66
80
 
67
81
  // App-related colors
68
82
  console.log(color.app('my-awesome-app')); // Purple, bold with app icon
@@ -93,21 +107,21 @@ See the [COLORS.md](docs/COLORS.md) documentation for the complete color palette
93
107
  #### Error Classes
94
108
 
95
109
  ```js
96
- import { utils } from '@heroku/heroku-cli-util';
110
+ import { AmbiguousError, NotFound } from '@heroku/heroku-cli-util/utils';
97
111
 
98
112
  // Error types
99
113
  try {
100
- throw new utils.errors.AmbiguousError([{ name: 'foo' }, { name: 'bar' }], 'addon');
114
+ throw new AmbiguousError([{ name: 'foo' }, { name: 'bar' }], 'addon');
101
115
  } catch (err) {
102
- if (err instanceof utils.errors.AmbiguousError) {
116
+ if (err instanceof AmbiguousError) {
103
117
  console.error('Ambiguous:', err.message);
104
118
  }
105
119
  }
106
120
 
107
121
  try {
108
- throw new utils.errors.NotFound();
122
+ throw new NotFound();
109
123
  } catch (err) {
110
- if (err instanceof utils.errors.NotFound) {
124
+ if (err instanceof NotFound) {
111
125
  console.error('Not found:', err.message);
112
126
  }
113
127
  }
@@ -155,16 +169,25 @@ import type {
155
169
  ### Database and Utility Helpers
156
170
 
157
171
  ```js
158
- import { utils } from '@heroku/heroku-cli-util';
172
+ import { DatabaseResolver, PsqlService, getHost, getPsqlConfigs } from '@heroku/heroku-cli-util/utils/pg';
173
+ import { AddonResolver, isPostgresAddon } from '@heroku/heroku-cli-util/utils/addons';
159
174
 
160
- // Get Heroku Postgres database connection details (requires APIClient from @heroku-cli/command)
161
- // const db = await utils.pg.databases(herokuApiClient, 'my-app', 'DATABASE_URL');
175
+ // Resolve a database from an app (requires APIClient from @heroku-cli/command)
176
+ const resolver = new DatabaseResolver(herokuApiClient, app, db);
177
+ const database = await resolver.resolve();
162
178
 
163
179
  // Get Heroku Postgres host
164
- const host = utils.pg.host();
180
+ const host = getHost();
181
+
182
+ // Create a PSQL service
183
+ const psql = new PsqlService(database);
184
+
185
+ // Check if addon is PostgreSQL
186
+ const isPg = isPostgresAddon(addon);
165
187
 
166
- // Run a query (requires a ConnectionDetails object)
167
- // const result = await utils.pg.psql.exec(db, 'SELECT 1');
188
+ // Resolve an addon
189
+ const addonResolver = new AddonResolver(herokuApiClient, app, addonName);
190
+ const addon = await addonResolver.resolve();
168
191
  ```
169
192
 
170
193
  ## Development
package/dist/index.d.ts CHANGED
@@ -37,9 +37,8 @@ export declare const utils: {
37
37
  NotFound: typeof NotFound;
38
38
  };
39
39
  pg: {
40
- DatabaseResolver: typeof DatabaseResolver;
41
- PsqlService: typeof PsqlService;
42
40
  addonService: () => string;
41
+ DatabaseResolver: typeof DatabaseResolver;
43
42
  host: typeof getHost;
44
43
  isAdvancedDatabase: (addon: DataApiTypes.ExtendedAddon | DataApiTypes.ExtendedAddonAttachment["addon"]) => boolean;
45
44
  isAdvancedPrivateDatabase: (addon: DataApiTypes.ExtendedAddon | DataApiTypes.ExtendedAddonAttachment["addon"]) => boolean;
@@ -52,6 +51,7 @@ export declare const utils: {
52
51
  getPsqlConfigs: typeof getPsqlConfigs;
53
52
  sshTunnel: typeof sshTunnel;
54
53
  };
54
+ PsqlService: typeof PsqlService;
55
55
  };
56
56
  };
57
57
  export declare const hux: {
package/dist/index.js CHANGED
@@ -10,8 +10,8 @@ import PsqlService from './utils/pg/psql.js';
10
10
  import { ago } from './ux/ago.js';
11
11
  import { alignColumns } from './ux/align-columns.js';
12
12
  import { anykey } from './ux/any-key.js';
13
- import { confirm } from './ux/confirm.js';
14
13
  import { confirmCommand } from './ux/confirm-command.js';
14
+ import { confirm } from './ux/confirm.js';
15
15
  import { toHumanReadableDataSize } from './ux/data-size.js';
16
16
  import { formatPrice } from './ux/format-price.js';
17
17
  import { openUrl } from './ux/open-url.js';
@@ -29,9 +29,8 @@ export const utils = {
29
29
  NotFound, // This should be NotFoundError for consistency, but we're keeping it for backwards compatibility
30
30
  },
31
31
  pg: {
32
- DatabaseResolver,
33
- PsqlService,
34
32
  addonService: getAddonService,
33
+ DatabaseResolver,
35
34
  host: getHost,
36
35
  isAdvancedDatabase,
37
36
  isAdvancedPrivateDatabase,
@@ -44,6 +43,7 @@ export const utils = {
44
43
  getPsqlConfigs,
45
44
  sshTunnel,
46
45
  },
46
+ PsqlService,
47
47
  },
48
48
  };
49
49
  export const hux = {
@@ -10,44 +10,44 @@ type AddonDescriptor = DeepRequired<Heroku.AddOnAttachment>['addon'];
10
10
  * This is the modified type for the `addon` property when the request to Platform API includes the value `addon:plan`
11
11
  * in the `Accept-Inclusion` header.
12
12
  */
13
- type AddonDescriptorWithPlanInclusion = {
13
+ type AddonDescriptorWithPlanInclusion = AddonDescriptor & {
14
14
  plan: {
15
15
  id: string;
16
16
  name: string;
17
17
  };
18
- } & AddonDescriptor;
18
+ };
19
19
  /**
20
20
  * This is the modified type for the `AddOnAttachment` type when the request to Platform API includes the value
21
21
  * `config_vars` in the `Accept-Inclusion` header.
22
22
  */
23
- type AddonAttachmentWithConfigVarsInclusion = {
23
+ type AddonAttachmentWithConfigVarsInclusion = DeepRequired<Heroku.AddOnAttachment> & {
24
24
  config_vars: string[];
25
- } & DeepRequired<Heroku.AddOnAttachment>;
25
+ };
26
26
  /**
27
27
  * This is the modified type for the `AddOnAttachment` we use on these lib functions because all requests made to
28
28
  * Platform API to get add-on attachments, either through the Add-on Attachment List endpoint or the
29
29
  * add-on attachment resolver action endpoint, include the header `Accept-Inclusion: addon:plan,config_vars`.
30
30
  */
31
- export type ExtendedAddonAttachment = {
31
+ export type ExtendedAddonAttachment = AddonAttachmentWithConfigVarsInclusion & {
32
32
  addon: AddonDescriptorWithPlanInclusion;
33
- } & AddonAttachmentWithConfigVarsInclusion;
33
+ };
34
34
  /**
35
35
  * This is the modified type for the `AddOn` we use on these lib functions because all requests made to
36
36
  * Platform API to get add-ons, either through the Add-on List endpoint or the add-on resolver action endpoint,
37
37
  * include the header `Accept-Expansion: addon_service,plan`.
38
38
  */
39
- export type ExtendedAddon = {
39
+ export type ExtendedAddon = DeepRequired<Heroku.AddOn> & {
40
40
  addon_service: DeepRequired<Heroku.AddOnService>;
41
41
  plan: DeepRequired<Heroku.Plan>;
42
- } & DeepRequired<Heroku.AddOn>;
42
+ };
43
43
  /**
44
44
  * The next two types need review and cleanup. They're not used anywhere in this codebase yet.
45
45
  */
46
- export type AddOnWithRelatedData = {
46
+ export type AddOnWithRelatedData = AddonDescriptor & {
47
47
  attachment_names?: string[];
48
48
  links?: Link[];
49
49
  plan: DeepRequired<Heroku.AddOn['plan']>;
50
- } & AddonDescriptor;
50
+ };
51
51
  export type Link = {
52
52
  attachment_name?: string;
53
53
  created_at: string;
@@ -1,6 +1,6 @@
1
1
  import { Server } from 'node:net';
2
2
  import type { ExtendedAddonAttachment } from './platform-api.js';
3
- export type ConnectionDetails = {
3
+ export type ConnectionDetails = BastionConfig & {
4
4
  _tunnel?: Server;
5
5
  attachment?: ExtendedAddonAttachment;
6
6
  database: string;
@@ -10,7 +10,7 @@ export type ConnectionDetails = {
10
10
  port: string;
11
11
  url: string;
12
12
  user: string;
13
- } & BastionConfig;
13
+ };
14
14
  export interface TunnelConfig {
15
15
  dstHost: string;
16
16
  dstPort: number;
@@ -0,0 +1,3 @@
1
+ export { default as AddonResolver } from './addon-resolver.js';
2
+ export { default as AttachmentResolver } from './attachment-resolver.js';
3
+ export { getAddonService, isAdvancedDatabase, isAdvancedPrivateDatabase, isEssentialDatabase, isLegacyDatabase, isLegacyEssentialDatabase, isPostgresAddon, } from './helpers.js';
@@ -0,0 +1,3 @@
1
+ export { default as AddonResolver } from './addon-resolver.js';
2
+ export { default as AttachmentResolver } from './attachment-resolver.js';
3
+ export { getAddonService, isAdvancedDatabase, isAdvancedPrivateDatabase, isEssentialDatabase, isLegacyDatabase, isLegacyEssentialDatabase, isPostgresAddon, } from './helpers.js';
@@ -0,0 +1,9 @@
1
+ export { AmbiguousError } from '../errors/ambiguous.js';
2
+ export { NotFound } from '../errors/not-found.js';
3
+ export { default as AddonResolver } from './addons/addon-resolver.js';
4
+ export { getAddonService, isAdvancedDatabase, isAdvancedPrivateDatabase, isEssentialDatabase, isLegacyDatabase, isLegacyEssentialDatabase, isPostgresAddon, } from './addons/helpers.js';
5
+ export { getPsqlConfigs, sshTunnel } from './pg/bastion.js';
6
+ export { getConfigVarNameFromAttachment } from './pg/config-vars.js';
7
+ export { default as DatabaseResolver } from './pg/databases.js';
8
+ export { default as getHost } from './pg/host.js';
9
+ export { default as PsqlService } from './pg/psql.js';
@@ -0,0 +1,9 @@
1
+ export { AmbiguousError } from '../errors/ambiguous.js';
2
+ export { NotFound } from '../errors/not-found.js';
3
+ export { default as AddonResolver } from './addons/addon-resolver.js';
4
+ export { getAddonService, isAdvancedDatabase, isAdvancedPrivateDatabase, isEssentialDatabase, isLegacyDatabase, isLegacyEssentialDatabase, isPostgresAddon, } from './addons/helpers.js';
5
+ export { getPsqlConfigs, sshTunnel } from './pg/bastion.js';
6
+ export { getConfigVarNameFromAttachment } from './pg/config-vars.js';
7
+ export { default as DatabaseResolver } from './pg/databases.js';
8
+ export { default as getHost } from './pg/host.js';
9
+ export { default as PsqlService } from './pg/psql.js';
@@ -1,5 +1,5 @@
1
- import type { HTTP } from '@heroku/http-call';
2
1
  import type { APIClient } from '@heroku-cli/command';
2
+ import type { HTTP } from '@heroku/http-call';
3
3
  import type { ExtendedAddonAttachment } from '../../types/pg/platform-api.js';
4
4
  /**
5
5
  * Cache of app config vars.
@@ -25,9 +25,9 @@ export default class DatabaseResolver {
25
25
  * @returns Promise resolving to all Heroku Postgres databases
26
26
  * @throws {Error} When no legacy database add-on exists on the app
27
27
  */
28
- getAllLegacyDatabases(app: string): Promise<Array<{
28
+ getAllLegacyDatabases(app: string): Promise<Array<ExtendedAddonAttachment['addon'] & {
29
29
  attachment_names?: string[];
30
- } & ExtendedAddonAttachment['addon']>>;
30
+ }>>;
31
31
  /**
32
32
  * Resolves an arbitrary legacy database add-on based on the provided app name.
33
33
  *
@@ -1 +1 @@
1
- export default function (): string;
1
+ export default function getHost(): string;
@@ -1,4 +1,4 @@
1
- export default function () {
1
+ export default function getHost() {
2
2
  const host = process.env.HEROKU_DATA_HOST || process.env.HEROKU_POSTGRESQL_HOST;
3
3
  return host ?? 'api.data.heroku.com';
4
4
  }
@@ -0,0 +1,5 @@
1
+ export { getPsqlConfigs, sshTunnel } from './bastion.js';
2
+ export { getConfigVarNameFromAttachment } from './config-vars.js';
3
+ export { default as DatabaseResolver } from './databases.js';
4
+ export { default as getHost } from './host.js';
5
+ export { default as PsqlService } from './psql.js';
@@ -0,0 +1,5 @@
1
+ export { getPsqlConfigs, sshTunnel } from './bastion.js';
2
+ export { getConfigVarNameFromAttachment } from './config-vars.js';
3
+ export { default as DatabaseResolver } from './databases.js';
4
+ export { default as getHost } from './host.js';
5
+ export { default as PsqlService } from './psql.js';
@@ -14,7 +14,8 @@ function readChar() {
14
14
  export async function anykey(message) {
15
15
  const { isRaw, isTTY } = process.stdin;
16
16
  if (!message) {
17
- message = isTTY ? `Press any key to continue or ${color.yellow('q')} to exit`
17
+ message = isTTY
18
+ ? `Press any key to continue or ${color.yellow('q')} to exit`
18
19
  : `Press enter to continue or ${color.yellow('q')} to exit`;
19
20
  }
20
21
  if (isTTY)
@@ -38,19 +38,28 @@ export async function confirmCommand({ abortedMessage, comparison, confirmation,
38
38
  if (confirmation) {
39
39
  if (confirmation === comparison)
40
40
  return;
41
- throw new Error(`Confirmation ${color.bold.red(confirmation)} did not match ${color.bold.red(comparison)}. ${abortedMessage}`);
41
+ throw new Error(`Confirmation ${color.warning(confirmation)} did not match ${color.info(comparison)}. ${abortedMessage}`);
42
42
  }
43
43
  if (!warningMessage) {
44
- warningMessage = heredoc `
44
+ warningMessage = heredoc(`
45
45
  Destructive Action
46
- This command will affect the app ${color.bold.red(comparison)}
47
- `;
46
+ This command will affect the app ${color.app(comparison)}
47
+ `).trimEnd();
48
48
  }
49
49
  ux.warn(warningMessage);
50
50
  process.stderr.write('\n');
51
- const entered = await promptFunction(`To proceed, type ${color.bold.red(comparison)} or re-run this command with ${color.bold.red(`--confirm ${comparison}`)}`, { required: true });
52
- if (entered === comparison) {
53
- return;
51
+ try {
52
+ const entered = await promptFunction(`To proceed, type ${color.warning(comparison)} or re-run this command with ${color.code(`--confirm ${comparison}`)}`, { required: true });
53
+ if (entered === comparison) {
54
+ return;
55
+ }
56
+ throw new Error(`Confirmation did not match ${color.info(comparison)}. ${abortedMessage}`);
57
+ }
58
+ catch (error) {
59
+ const err = error;
60
+ if (err.name === 'ExitPromptError' && err.message.includes('SIGINT')) {
61
+ throw new Error(`Cancelled with ${color.warning('CTRL+C')}. ${abortedMessage}`);
62
+ }
63
+ throw error;
54
64
  }
55
- throw new Error(`Confirmation did not match ${color.bold.red(comparison)}. ${abortedMessage}`);
56
65
  }
@@ -0,0 +1,16 @@
1
+ export { ago } from './ago.js';
2
+ export { alignColumns } from './align-columns.js';
3
+ export { anykey } from './any-key.js';
4
+ export * as color from './colors.js';
5
+ export { confirmCommand } from './confirm-command.js';
6
+ export { confirm } from './confirm.js';
7
+ export { toHumanReadableDataSize } from './data-size.js';
8
+ export { formatPrice } from './format-price.js';
9
+ export { openUrl } from './open-url.js';
10
+ export { prompt } from './prompt.js';
11
+ export { styledHeader } from './styled-header.js';
12
+ export { styledJSON } from './styled-json.js';
13
+ export { styledObject } from './styled-object.js';
14
+ export { table } from './table.js';
15
+ export { toTitleCase } from './to-title-case.js';
16
+ export { wait } from './wait.js';
@@ -0,0 +1,16 @@
1
+ export { ago } from './ago.js';
2
+ export { alignColumns } from './align-columns.js';
3
+ export { anykey } from './any-key.js';
4
+ export * as color from './colors.js';
5
+ export { confirmCommand } from './confirm-command.js';
6
+ export { confirm } from './confirm.js';
7
+ export { toHumanReadableDataSize } from './data-size.js';
8
+ export { formatPrice } from './format-price.js';
9
+ export { openUrl } from './open-url.js';
10
+ export { prompt } from './prompt.js';
11
+ export { styledHeader } from './styled-header.js';
12
+ export { styledJSON } from './styled-json.js';
13
+ export { styledObject } from './styled-object.js';
14
+ export { table } from './table.js';
15
+ export { toTitleCase } from './to-title-case.js';
16
+ export { wait } from './wait.js';
@@ -8,7 +8,7 @@ type Column<T extends Record<string, unknown>> = {
8
8
  type Columns<T extends Record<string, unknown>> = {
9
9
  [key: string]: Partial<Column<T>>;
10
10
  };
11
- export declare function table<T extends Record<string, unknown>>(data: T[], columns: Columns<T>, options?: {
11
+ export declare function table<T extends Record<string, unknown>>(data: T[], columns: Columns<T>, options?: Omit<TableOptions<T>, 'columns' | 'data'> & {
12
12
  printLine?(s: unknown): void;
13
- } & Omit<TableOptions<T>, 'columns' | 'data'>): void;
13
+ }): void;
14
14
  export {};
package/dist/ux/table.js CHANGED
@@ -9,14 +9,16 @@ export function table(data, columns, options) {
9
9
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
10
10
  const { printLine, ...tableOptions } = options || {};
11
11
  printTable({
12
- ...(tableOptions?.noStyle ? {} : {
13
- borderColor: 'whiteBright',
14
- borderStyle: 'headers-only-with-underline',
15
- headerOptions: {
16
- bold: true,
17
- color: 'white', // or 'reset' to use default terminal color
18
- },
19
- }),
12
+ ...(tableOptions?.noStyle
13
+ ? {}
14
+ : {
15
+ borderColor: 'whiteBright',
16
+ borderStyle: 'headers-only-with-underline',
17
+ headerOptions: {
18
+ bold: true,
19
+ color: 'white', // or 'reset' to use default terminal color
20
+ },
21
+ }),
20
22
  ...tableOptions,
21
23
  columns: cols,
22
24
  data: d,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@heroku/heroku-cli-util",
4
- "version": "10.6.1",
4
+ "version": "10.7.0-beta.0",
5
5
  "description": "Set of helpful CLI utilities",
6
6
  "author": "Heroku",
7
7
  "license": "ISC",
@@ -11,36 +11,71 @@
11
11
  },
12
12
  "main": "dist/index.js",
13
13
  "types": "dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js",
18
+ "default": "./dist/index.js"
19
+ },
20
+ "./color": {
21
+ "types": "./dist/ux/colors.d.ts",
22
+ "import": "./dist/ux/colors.js",
23
+ "default": "./dist/ux/colors.js"
24
+ },
25
+ "./colors": {
26
+ "types": "./dist/ux/colors.d.ts",
27
+ "import": "./dist/ux/colors.js",
28
+ "default": "./dist/ux/colors.js"
29
+ },
30
+ "./hux": {
31
+ "types": "./dist/ux/index.d.ts",
32
+ "import": "./dist/ux/index.js",
33
+ "default": "./dist/ux/index.js"
34
+ },
35
+ "./utils": {
36
+ "types": "./dist/utils/index.d.ts",
37
+ "import": "./dist/utils/index.js",
38
+ "default": "./dist/utils/index.js"
39
+ },
40
+ "./utils/pg": {
41
+ "types": "./dist/utils/pg/index.d.ts",
42
+ "import": "./dist/utils/pg/index.js",
43
+ "default": "./dist/utils/pg/index.js"
44
+ },
45
+ "./utils/addons": {
46
+ "types": "./dist/utils/addons/index.d.ts",
47
+ "import": "./dist/utils/addons/index.js",
48
+ "default": "./dist/utils/addons/index.js"
49
+ }
50
+ },
14
51
  "files": [
15
52
  "dist"
16
53
  ],
17
54
  "devDependencies": {
18
55
  "@heroku-cli/schema": "^2.0.0",
19
- "@heroku-cli/test-utils": "^0.1.2",
20
- "@types/chai": "^4.3.13",
56
+ "@heroku-cli/test-utils": "^0.2.0",
57
+ "@types/chai": "^5.2.3",
21
58
  "@types/chai-as-promised": "^8.0.2",
22
59
  "@types/debug": "^4.1.12",
23
60
  "@types/mocha": "^10.0.10",
24
61
  "@types/node": "^22.15.3",
25
- "@types/sinon": "^17.0.4",
62
+ "@types/sinon": "^20.0.0",
26
63
  "@types/sinon-chai": "^4.0.0",
27
64
  "@types/tmp": "^0.2.6",
28
65
  "@types/tunnel-ssh": "4.1.1",
29
- "c8": "^7.7.0",
30
- "chai": "^4.4.1",
31
- "chai-as-promised": "^8.0.1",
66
+ "c8": "^11.0.0",
67
+ "chai": "^5.3.3",
68
+ "chai-as-promised": "^8.0.2",
32
69
  "eslint": "^9",
33
70
  "eslint-config-oclif": "^6.0.144",
34
- "eslint-plugin-mocha": "^11.2.0",
35
71
  "mocha": "^11",
36
72
  "mock-stdin": "^1.0.0",
37
- "nock": "^13.2.9",
73
+ "nock": "^14.0.11",
38
74
  "open": "^11",
39
- "sinon": "^18.0.1",
40
- "sinon-chai": "^3.7.0",
75
+ "sinon": "^20.0.0",
76
+ "sinon-chai": "^4.0.1",
41
77
  "tmp": "^0.2.5",
42
- "ts-node": "^10.9.2",
43
- "tsconfig-paths": "^4.2.0",
78
+ "tsx": "^4.21.0",
44
79
  "typescript": "^5.4.0"
45
80
  },
46
81
  "dependencies": {
@@ -63,10 +98,9 @@
63
98
  "clean": "rm -rf dist",
64
99
  "example": "sh examples/run.sh",
65
100
  "lint": "eslint .",
66
- "posttest": "npm run lint",
101
+ "lint:fix": "eslint --fix",
67
102
  "prepare": "npm run build",
68
- "test": "c8 mocha --forbid-only \"test/**/*.test.ts\"",
69
- "test:local": "c8 mocha \"${npm_config_file:-test/**/*.test.+(ts|tsx)}\""
103
+ "test": "npm run build && c8 --all --check-coverage --reporter=lcov --reporter=text-summary mocha --forbid-only \"test/**/*.test.ts\""
70
104
  },
71
105
  "overrides": {
72
106
  "serialize-javascript": "^7.0.3"