@finopsbricks/fob-snap 0.1.0 → 0.1.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finopsbricks/fob-snap",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Snapshots app client + fob-snap CLI (2-in-1). Import the client in workers, or use the CLI to push snapshots and manage widgets/dashboards.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -60,3 +60,32 @@ export function listOptions(cmd) {
60
60
  .option('--page <n>', 'Page number', Number, 1)
61
61
  .option('--limit <n>', 'Page size (max 500)', Number, 100);
62
62
  }
63
+
64
+ /**
65
+ * Help formatting for the whole tree, per the CLI standard's command-grammar note
66
+ * (Options: above Global Options:, hang-indented descriptions).
67
+ *
68
+ * `subcommandTerm` drops commander's default `[options]` suffix so the name column
69
+ * stays narrow enough for descriptions to wrap cleanly; aliases are preserved
70
+ * (`remove|rm`), since help is the only place a reader discovers them.
71
+ *
72
+ * `showGlobalOptions` renders the mandated `Options:` / `Global Options:` split.
73
+ *
74
+ * Commander does not inherit `configureHelp()` through `addCommand()`, so this
75
+ * walks the tree rather than being set once at the root.
76
+ */
77
+ export function configureTreeHelp(cmd) {
78
+ cmd.configureHelp({
79
+ helpWidth: process.stdout.columns || 92,
80
+ showGlobalOptions: true,
81
+ subcommandTerm: (c) => {
82
+ const name = c.aliases().length ? `${c.name()}|${c.aliases().join('|')}` : c.name();
83
+ return `${name} ${c.usage().replace(/\[options\] ?/, '')}`.trim();
84
+ },
85
+ // Commander adds an implicit `help [command]` subcommand; `--help` is already
86
+ // under Options:, so the row is noise in a resource listing.
87
+ visibleCommands: (c) => c.commands.filter((sub) => sub.name() !== 'help' && !sub._hidden),
88
+ });
89
+ for (const child of cmd.commands) configureTreeHelp(child);
90
+ return cmd;
91
+ }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * A profile is a named `{ api_url, api_key, api_secret }` set stored in
5
5
  * ~/.fob/fob-snap/config.yml. `add` takes flags, or prompts interactively for any
6
- * missing credential (secret via a hidden prompt) — the `login` flow.
6
+ * missing credential (secret via a hidden prompt).
7
7
  */
8
8
 
9
9
  import { Command } from 'commander';
@@ -58,7 +58,7 @@ function currentHandler(argv) {
58
58
  }
59
59
 
60
60
  function buildProfilesCommand() {
61
- const profiles = new Command('profiles').alias('login').description('Manage credential profiles');
61
+ const profiles = new Command('profiles').description('Manage credential profiles');
62
62
 
63
63
  profiles
64
64
  .command('add')
@@ -62,7 +62,7 @@ async function unshareHandler(argv) {
62
62
  }
63
63
 
64
64
  export function buildDashboardsCommand() {
65
- const dashboards = new Command('dashboards').alias('dashboard').description('Manage dashboards, placements, and share links');
65
+ const dashboards = new Command('dashboards').description('Manage dashboards, placements, and share links');
66
66
 
67
67
  listOptions(dashboards.command('list').description("List the org's dashboards")).action(safe(listHandler));
68
68
  jsonOption(dashboards.command('show').description('Show a dashboard with its placements').argument('<id>', 'Dashboard id')).action(safe(showHandler));
@@ -74,7 +74,7 @@ export function buildDashboardsCommand() {
74
74
  .option('--json', 'Output raw JSON')
75
75
  .action(safe(createHandler));
76
76
 
77
- dashboards.command('delete').alias('rm').description('Delete a dashboard').argument('<id>', 'Dashboard id').action(safe(deleteHandler));
77
+ dashboards.command('delete').description('Delete a dashboard').argument('<id>', 'Dashboard id').action(safe(deleteHandler));
78
78
 
79
79
  dashboards
80
80
  .command('add-widget')
package/src/cli/index.js CHANGED
@@ -13,6 +13,7 @@ import { dirname, join } from 'node:path';
13
13
  import { Command } from 'commander';
14
14
 
15
15
  import { setProfileOverride } from './config-store.js';
16
+ import { safe, configureTreeHelp } from './_helpers.js';
16
17
  import { gettingStartedHandler } from './getting-started.js';
17
18
  import { buildConfigCommand } from './config/index.js';
18
19
  import { buildSnapshotsCommand } from './snapshots/index.js';
@@ -30,9 +31,9 @@ export function run(argv) {
30
31
  program
31
32
  .name('fob-snap')
32
33
  .usage('<resource> <action> [target] [options]')
33
- .description('Push snapshots and manage widgets/dashboards for Snapshots (snapshots.finopsbricks.com).')
34
34
  .version(packageVersion(), '-v, --version', 'Show version number')
35
- .option('--profile <name>', 'Use credentials from a specific configured profile')
35
+ .option('--profile <name>', 'Use credentials from a specific configured profile (overrides current)')
36
+ // Runs before any action handler, at any depth.
36
37
  .hook('preAction', (thisCommand) => {
37
38
  const { profile } = thisCommand.opts();
38
39
  if (profile) setProfileOverride(profile);
@@ -41,7 +42,7 @@ export function run(argv) {
41
42
  program
42
43
  .command('getting-started')
43
44
  .description('Print setup instructions')
44
- .action(gettingStartedHandler);
45
+ .action(safe(gettingStartedHandler));
45
46
 
46
47
  program
47
48
  .addCommand(buildConfigCommand())
@@ -51,5 +52,8 @@ export function run(argv) {
51
52
  .allowUnknownOption(false)
52
53
  .showHelpAfterError();
53
54
 
55
+ // Applied tree-wide because configureHelp() is not inherited through addCommand().
56
+ configureTreeHelp(program);
57
+
54
58
  program.parse(argv, { from: 'user' });
55
59
  }
@@ -52,7 +52,7 @@ async function listHandler(argv) {
52
52
  }
53
53
 
54
54
  export function buildSnapshotsCommand() {
55
- const snapshots = new Command('snapshots').alias('snap').description('Push and list snapshot versions');
55
+ const snapshots = new Command('snapshots').description('Push and list snapshot versions');
56
56
 
57
57
  snapshots
58
58
  .command('push')
@@ -62,7 +62,7 @@ async function deleteHandler(argv) {
62
62
  }
63
63
 
64
64
  export function buildWidgetsCommand() {
65
- const widgets = new Command('widgets').alias('widget').description('Manage widgets');
65
+ const widgets = new Command('widgets').description('Manage widgets');
66
66
 
67
67
  listOptions(widgets.command('list').description("List the org's widgets")).action(safe(listHandler));
68
68
  jsonOption(widgets.command('show').description('Show one widget').argument('<id>', 'Widget id')).action(safe(showHandler));
@@ -77,7 +77,7 @@ export function buildWidgetsCommand() {
77
77
  .option('--json', 'Output raw JSON')
78
78
  .action(safe(createHandler));
79
79
 
80
- widgets.command('delete').alias('rm').description('Delete a widget (snapshots cascade)').argument('<id>', 'Widget id').action(safe(deleteHandler));
80
+ widgets.command('delete').description('Delete a widget (snapshots cascade)').argument('<id>', 'Widget id').action(safe(deleteHandler));
81
81
 
82
82
  return widgets;
83
83
  }