bktide 1.0.1755267617 → 1.0.1755559112

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.
Files changed (93) hide show
  1. package/README.md +107 -1
  2. package/WORKFLOW_README.md +1 -1
  3. package/completions/bktide-dynamic.fish +171 -0
  4. package/completions/bktide.bash +124 -0
  5. package/completions/bktide.fish +107 -0
  6. package/completions/bktide.zsh +139 -0
  7. package/dist/commands/BaseCommand.js +7 -7
  8. package/dist/commands/BaseCommand.js.map +1 -1
  9. package/dist/commands/GenerateCompletions.js +238 -0
  10. package/dist/commands/GenerateCompletions.js.map +1 -0
  11. package/dist/commands/ListAnnotations.js +7 -0
  12. package/dist/commands/ListAnnotations.js.map +1 -1
  13. package/dist/commands/ListBuilds.js +67 -3
  14. package/dist/commands/ListBuilds.js.map +1 -1
  15. package/dist/commands/ListOrganizations.js +6 -0
  16. package/dist/commands/ListOrganizations.js.map +1 -1
  17. package/dist/commands/ListPipelines.js +87 -12
  18. package/dist/commands/ListPipelines.js.map +1 -1
  19. package/dist/commands/ManageToken.js +32 -9
  20. package/dist/commands/ManageToken.js.map +1 -1
  21. package/dist/commands/ShowBuild.js +88 -0
  22. package/dist/commands/ShowBuild.js.map +1 -0
  23. package/dist/commands/ShowViewer.js +7 -1
  24. package/dist/commands/ShowViewer.js.map +1 -1
  25. package/dist/commands/index.js +2 -0
  26. package/dist/commands/index.js.map +1 -1
  27. package/dist/formatters/FormatterFactory.js +4 -0
  28. package/dist/formatters/FormatterFactory.js.map +1 -1
  29. package/dist/formatters/annotations/PlainTextFormatter.js +37 -9
  30. package/dist/formatters/annotations/PlainTextFormatter.js.map +1 -1
  31. package/dist/formatters/build-detail/AlfredFormatter.js +113 -0
  32. package/dist/formatters/build-detail/AlfredFormatter.js.map +1 -0
  33. package/dist/formatters/build-detail/Formatter.js +3 -0
  34. package/dist/formatters/build-detail/Formatter.js.map +1 -0
  35. package/dist/formatters/build-detail/JsonFormatter.js +132 -0
  36. package/dist/formatters/build-detail/JsonFormatter.js.map +1 -0
  37. package/dist/formatters/build-detail/PlainTextFormatter.js +680 -0
  38. package/dist/formatters/build-detail/PlainTextFormatter.js.map +1 -0
  39. package/dist/formatters/build-detail/index.js +21 -0
  40. package/dist/formatters/build-detail/index.js.map +1 -0
  41. package/dist/formatters/builds/PlainTextFormatter.js +82 -60
  42. package/dist/formatters/builds/PlainTextFormatter.js.map +1 -1
  43. package/dist/formatters/errors/AlfredFormatter.js +20 -0
  44. package/dist/formatters/errors/AlfredFormatter.js.map +1 -1
  45. package/dist/formatters/errors/PlainTextFormatter.js +121 -23
  46. package/dist/formatters/errors/PlainTextFormatter.js.map +1 -1
  47. package/dist/formatters/organizations/PlainTextFormatter.js +37 -6
  48. package/dist/formatters/organizations/PlainTextFormatter.js.map +1 -1
  49. package/dist/formatters/pipelines/AlfredFormatter.js.map +1 -1
  50. package/dist/formatters/pipelines/Formatter.js.map +1 -1
  51. package/dist/formatters/pipelines/JsonFormatter.js.map +1 -1
  52. package/dist/formatters/pipelines/PlainTextFormatter.js +165 -19
  53. package/dist/formatters/pipelines/PlainTextFormatter.js.map +1 -1
  54. package/dist/formatters/token/AlfredFormatter.js +15 -2
  55. package/dist/formatters/token/AlfredFormatter.js.map +1 -1
  56. package/dist/formatters/token/PlainTextFormatter.js +56 -18
  57. package/dist/formatters/token/PlainTextFormatter.js.map +1 -1
  58. package/dist/formatters/viewer/PlainTextFormatter.js +8 -7
  59. package/dist/formatters/viewer/PlainTextFormatter.js.map +1 -1
  60. package/dist/graphql/queries.js +181 -0
  61. package/dist/graphql/queries.js.map +1 -1
  62. package/dist/index.js +67 -6
  63. package/dist/index.js.map +1 -1
  64. package/dist/services/BuildkiteClient.js +61 -1
  65. package/dist/services/BuildkiteClient.js.map +1 -1
  66. package/dist/services/CredentialManager.js +80 -10
  67. package/dist/services/CredentialManager.js.map +1 -1
  68. package/dist/ui/help.js +69 -0
  69. package/dist/ui/help.js.map +1 -0
  70. package/dist/ui/progress.js +356 -0
  71. package/dist/ui/progress.js.map +1 -0
  72. package/dist/ui/reporter.js +111 -0
  73. package/dist/ui/reporter.js.map +1 -0
  74. package/dist/ui/responsive-table.js +183 -0
  75. package/dist/ui/responsive-table.js.map +1 -0
  76. package/dist/ui/spinner.js +20 -0
  77. package/dist/ui/spinner.js.map +1 -0
  78. package/dist/ui/symbols.js +46 -0
  79. package/dist/ui/symbols.js.map +1 -0
  80. package/dist/ui/table.js +32 -0
  81. package/dist/ui/table.js.map +1 -0
  82. package/dist/ui/theme.js +280 -0
  83. package/dist/ui/theme.js.map +1 -0
  84. package/dist/ui/width.js +111 -0
  85. package/dist/ui/width.js.map +1 -0
  86. package/dist/utils/alfred.js +6 -0
  87. package/dist/utils/alfred.js.map +1 -0
  88. package/dist/utils/cli-error-handler.js +35 -20
  89. package/dist/utils/cli-error-handler.js.map +1 -1
  90. package/dist/utils/pagination.js +92 -0
  91. package/dist/utils/pagination.js.map +1 -0
  92. package/info.plist +51 -218
  93. package/package.json +24 -5
@@ -2,6 +2,8 @@ import { BaseCommand } from './BaseCommand.js';
2
2
  import { getBuildFormatter } from '../formatters/index.js';
3
3
  import Fuse from 'fuse.js';
4
4
  import { logger } from '../services/logger.js';
5
+ import { Reporter } from '../ui/reporter.js';
6
+ import { Progress } from '../ui/progress.js';
5
7
  export class ListBuilds extends BaseCommand {
6
8
  constructor(options) {
7
9
  super(options);
@@ -13,8 +15,12 @@ export class ListBuilds extends BaseCommand {
13
15
  logger.debug('Starting ViewerBuildsCommandHandler execution');
14
16
  }
15
17
  try {
18
+ const format = options.format || 'plain';
19
+ const reporter = new Reporter(format, options.quiet, options.tips);
20
+ const viewerSpinner = Progress.spinner('Fetching viewer info...', { format });
16
21
  // First, get the current user's information using GraphQL
17
22
  const viewerData = await this.client.getViewer();
23
+ viewerSpinner.stop();
18
24
  if (!viewerData?.viewer?.user?.uuid) {
19
25
  logger.error('Failed to get current user UUID information');
20
26
  return 1;
@@ -43,12 +49,35 @@ export class ListBuilds extends BaseCommand {
43
49
  // Initialize results array
44
50
  let allBuilds = [];
45
51
  let accessErrors = [];
46
- for (const org of orgs) {
52
+ // Use progress bar for multiple orgs, spinner for single org
53
+ const useProgressBar = orgs.length > 1 && format === 'plain';
54
+ const progress = useProgressBar ? Progress.bar({
55
+ total: orgs.length,
56
+ label: 'Fetching builds from organizations',
57
+ format: format
58
+ }) : null;
59
+ // Create a spinner for single-org scenario
60
+ let fetchSpinner = !useProgressBar ? Progress.spinner(undefined, { format }) : null;
61
+ for (let i = 0; i < orgs.length; i++) {
62
+ const org = orgs[i];
47
63
  try {
64
+ if (progress) {
65
+ progress.update(i, `Fetching builds from ${org}`);
66
+ }
67
+ else if (fetchSpinner) {
68
+ fetchSpinner.update(`Fetching builds from ${org}…`, `Fetching builds from ${org}…`);
69
+ }
48
70
  // First check if the user has access to this organization
49
71
  const hasAccess = await this.restClient.hasOrganizationAccess(org);
50
72
  if (!hasAccess) {
51
73
  accessErrors.push(`You don't have access to organization ${org}`);
74
+ if (progress) {
75
+ // Continue to next org with progress bar
76
+ progress.update(i + 1, `No access to ${org}`);
77
+ }
78
+ else if (fetchSpinner) {
79
+ fetchSpinner.fail(`No access to ${org}`);
80
+ }
52
81
  continue;
53
82
  }
54
83
  const builds = await this.restClient.getBuilds(org, {
@@ -63,12 +92,23 @@ export class ListBuilds extends BaseCommand {
63
92
  logger.debug(`Received ${builds.length} builds from org ${org}`);
64
93
  }
65
94
  allBuilds = allBuilds.concat(builds);
95
+ if (!progress && fetchSpinner) {
96
+ fetchSpinner.stop();
97
+ }
66
98
  }
67
99
  catch (error) {
68
100
  // Log unexpected errors but continue processing other orgs
69
101
  logger.error(error, `Error fetching builds for org ${org}`);
102
+ if (!progress && fetchSpinner) {
103
+ fetchSpinner.stop();
104
+ }
70
105
  }
71
106
  }
107
+ // Complete the progress bar
108
+ if (progress) {
109
+ const successOrgs = orgs.length - accessErrors.length;
110
+ progress.complete(`Retrieved ${allBuilds.length} builds from ${successOrgs}/${orgs.length} organizations`);
111
+ }
72
112
  // Prepare formatter options
73
113
  const formatterOptions = {
74
114
  debug: options.debug,
@@ -116,10 +156,34 @@ export class ListBuilds extends BaseCommand {
116
156
  logger.debug(`Filtered to ${allBuilds.length} builds matching '${options.filter}'`);
117
157
  }
118
158
  }
119
- const format = options.format || 'plain';
120
159
  const formatter = getBuildFormatter(format);
121
160
  const output = formatter.formatBuilds(allBuilds, formatterOptions);
122
- logger.console(output);
161
+ // Output data directly to stdout to ensure proper ordering
162
+ if (format === 'plain') {
163
+ process.stdout.write(output + '\n');
164
+ }
165
+ else {
166
+ logger.console(output);
167
+ }
168
+ // Add contextual next-steps hints AFTER showing the data
169
+ if (allBuilds.length > 0) {
170
+ const tips = [];
171
+ const buildCount = parseInt(perPage, 10);
172
+ if (allBuilds.length === buildCount) {
173
+ tips.push(`Use --count ${buildCount * 2} to see more builds`);
174
+ }
175
+ // If filtering is not active, suggest filtering options
176
+ if (!options.state && !options.branch && !options.pipeline) {
177
+ tips.push('Filter by state: --state failed');
178
+ tips.push('Filter by branch: --branch main');
179
+ tips.push('Filter by pipeline: --pipeline <name>');
180
+ }
181
+ // Display all tips at once
182
+ if (tips.length > 0) {
183
+ // Use individual style for consistency with current output
184
+ tips.forEach(tip => reporter.tip(tip));
185
+ }
186
+ }
123
187
  if (options.debug) {
124
188
  const executeDuration = Number(process.hrtime.bigint() - executeStartTime) / 1000000;
125
189
  logger.debug(`ViewerBuildsCommandHandler execution completed in ${executeDuration.toFixed(2)}ms`);
@@ -1 +1 @@
1
- {"version":3,"file":"ListBuilds.js","sourceRoot":"/","sources":["commands/ListBuilds.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseCommand, BaseCommandOptions } from './BaseCommand.js';\nimport { getBuildFormatter } from '../formatters/index.js';\nimport Fuse from 'fuse.js';\nimport { Build } from '../types/index.js';\nimport { logger } from '../services/logger.js';\nimport { BuildFormatterOptions } from '../formatters/builds/Formatter.js';\n\nexport interface ViewerBuildsOptions extends BaseCommandOptions {\n count?: string;\n page?: string;\n org?: string;\n pipeline?: string;\n branch?: string;\n state?: string;\n}\n\nexport class ListBuilds extends BaseCommand {\n constructor(options?: Partial<ViewerBuildsOptions>) {\n super(options);\n }\n\n async execute(options: ViewerBuildsOptions): Promise<number> {\n await this.ensureInitialized();\n \n const executeStartTime = process.hrtime.bigint();\n if (options.debug) {\n logger.debug('Starting ViewerBuildsCommandHandler execution');\n }\n \n try {\n // First, get the current user's information using GraphQL\n const viewerData = await this.client.getViewer();\n \n if (!viewerData?.viewer?.user?.uuid) {\n logger.error('Failed to get current user UUID information');\n return 1;\n }\n \n const userId = viewerData.viewer.user.uuid;\n const userName = viewerData.viewer.user.name || 'Current user';\n const userEmail = viewerData.viewer.user.email;\n \n // Use the REST API to get builds by the current user\n const perPage = options.count || '10';\n const page = options.page || '1';\n \n // If organization is not specified, we need to fetch organizations first\n let orgs: string[] = [];\n if (!options.org) {\n // Try to fetch the user's organizations\n try {\n orgs = await this.client.getViewerOrganizationSlugs();\n } catch (error) {\n logger.error(error as any, 'Failed to determine your organizations');\n return 1;\n }\n } else {\n orgs = [options.org];\n }\n \n // Initialize results array\n let allBuilds: Build[] = [];\n let accessErrors: string[] = [];\n \n for (const org of orgs) {\n try {\n // First check if the user has access to this organization\n const hasAccess = await this.restClient.hasOrganizationAccess(org);\n if (!hasAccess) {\n accessErrors.push(`You don't have access to organization ${org}`);\n continue;\n }\n \n const builds = await this.restClient.getBuilds(org, {\n creator: userId,\n pipeline: options.pipeline,\n branch: options.branch,\n state: options.state,\n per_page: perPage,\n page: page\n });\n \n if (options.debug) {\n logger.debug(`Received ${builds.length} builds from org ${org}`);\n }\n \n allBuilds = allBuilds.concat(builds);\n } catch (error) {\n // Log unexpected errors but continue processing other orgs\n logger.error(error, `Error fetching builds for org ${org}`);\n }\n }\n \n // Prepare formatter options\n const formatterOptions: BuildFormatterOptions = {\n debug: options.debug,\n organizationsCount: orgs.length,\n orgSpecified: !!options.org,\n userName,\n userEmail,\n userId\n };\n \n // Handle the case where we have no builds due to access issues\n if (allBuilds.length === 0 && accessErrors.length > 0) {\n formatterOptions.hasError = true;\n formatterOptions.errorType = 'access';\n formatterOptions.accessErrors = accessErrors;\n \n if (options.org) {\n formatterOptions.errorMessage = `No builds found for ${userName} (${userEmail}) in organization ${options.org}. ${accessErrors[0]}`;\n } else {\n formatterOptions.errorMessage = `No builds found for ${userName} (${userEmail}). Try specifying an organization with --org to narrow your search.`;\n }\n \n const format = options.format || 'plain';\n const formatter = getBuildFormatter(format);\n const output = formatter.formatBuilds(allBuilds, formatterOptions);\n logger.console(output);\n return 1;\n }\n \n // Limit to the requested number of builds\n allBuilds = allBuilds.slice(0, parseInt(perPage, 10));\n \n // Apply fuzzy filter if specified\n if (options.filter) {\n if (options.debug) {\n logger.debug(`Applying fuzzy filter '${options.filter}' to ${allBuilds.length} builds`);\n }\n \n // Configure Fuse for fuzzy searching\n const fuse = new Fuse(allBuilds, {\n keys: ['pipeline.name', 'branch', 'message', 'creator.name', 'state'],\n threshold: 0.4,\n includeScore: true,\n shouldSort: true\n });\n \n // Perform the fuzzy search\n const searchResults = fuse.search(options.filter);\n allBuilds = searchResults.map(result => result.item);\n \n if (options.debug) {\n logger.debug(`Filtered to ${allBuilds.length} builds matching '${options.filter}'`);\n }\n }\n \n const format = options.format || 'plain';\n const formatter = getBuildFormatter(format);\n const output = formatter.formatBuilds(allBuilds, formatterOptions);\n logger.console(output);\n \n if (options.debug) {\n const executeDuration = Number(process.hrtime.bigint() - executeStartTime) / 1000000;\n logger.debug(`ViewerBuildsCommandHandler execution completed in ${executeDuration.toFixed(2)}ms`);\n }\n \n return 0; // Success\n } catch (error) {\n // Only unexpected errors should reach here\n // Let the base command handle the error display\n this.handleError(error, options.debug);\n return 1; // Error\n }\n }\n}"]}
1
+ {"version":3,"file":"ListBuilds.js","sourceRoot":"/","sources":["commands/ListBuilds.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,IAAI,MAAM,SAAS,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAY7C,MAAM,OAAO,UAAW,SAAQ,WAAW;IACzC,YAAY,OAAsC;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAA4B;QACxC,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACjD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC;YACzC,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YACnE,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,yBAAyB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAC9E,0DAA0D;YAC1D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YACjD,aAAa,CAAC,IAAI,EAAE,CAAC;YAErB,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;gBACpC,MAAM,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;gBAC5D,OAAO,CAAC,CAAC;YACX,CAAC;YAED,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;YAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,cAAc,CAAC;YAC/D,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;YAE/C,qDAAqD;YACrD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;YACtC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,CAAC;YAEjC,yEAAyE;YACzE,IAAI,IAAI,GAAa,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;gBACjB,wCAAwC;gBACxC,IAAI,CAAC;oBACH,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,0BAA0B,EAAE,CAAC;gBACxD,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,KAAK,CAAC,KAAY,EAAE,wCAAwC,CAAC,CAAC;oBACrE,OAAO,CAAC,CAAC;gBACX,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;YAED,2BAA2B;YAC3B,IAAI,SAAS,GAAY,EAAE,CAAC;YAC5B,IAAI,YAAY,GAAa,EAAE,CAAC;YAEhC,6DAA6D;YAC7D,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,KAAK,OAAO,CAAC;YAC7D,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAC7C,KAAK,EAAE,IAAI,CAAC,MAAM;gBAClB,KAAK,EAAE,oCAAoC;gBAC3C,MAAM,EAAE,MAAM;aACf,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAEV,2CAA2C;YAC3C,IAAI,YAAY,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAEpF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;gBAEpB,IAAI,CAAC;oBACH,IAAI,QAAQ,EAAE,CAAC;wBACb,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,wBAAwB,GAAG,EAAE,CAAC,CAAC;oBACpD,CAAC;yBAAM,IAAI,YAAY,EAAE,CAAC;wBACxB,YAAY,CAAC,MAAM,CAAC,wBAAwB,GAAG,GAAG,EAAE,wBAAwB,GAAG,GAAG,CAAC,CAAC;oBACtF,CAAC;oBAED,0DAA0D;oBAC1D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;oBACnE,IAAI,CAAC,SAAS,EAAE,CAAC;wBACf,YAAY,CAAC,IAAI,CAAC,yCAAyC,GAAG,EAAE,CAAC,CAAC;wBAClE,IAAI,QAAQ,EAAE,CAAC;4BACb,yCAAyC;4BACzC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,gBAAgB,GAAG,EAAE,CAAC,CAAC;wBAChD,CAAC;6BAAM,IAAI,YAAY,EAAE,CAAC;4BACxB,YAAY,CAAC,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC;wBAC3C,CAAC;wBACD,SAAS;oBACX,CAAC;oBAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE;wBAClD,OAAO,EAAE,MAAM;wBACf,QAAQ,EAAE,OAAO,CAAC,QAAQ;wBAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;wBACtB,KAAK,EAAE,OAAO,CAAC,KAAK;wBACpB,QAAQ,EAAE,OAAO;wBACjB,IAAI,EAAE,IAAI;qBACX,CAAC,CAAC;oBAEH,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;wBAClB,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC,CAAC;oBACnE,CAAC;oBAED,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;oBAErC,IAAI,CAAC,QAAQ,IAAI,YAAY,EAAE,CAAC;wBAC9B,YAAY,CAAC,IAAI,EAAE,CAAC;oBACtB,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,2DAA2D;oBAC3D,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,iCAAiC,GAAG,EAAE,CAAC,CAAC;oBAC5D,IAAI,CAAC,QAAQ,IAAI,YAAY,EAAE,CAAC;wBAC9B,YAAY,CAAC,IAAI,EAAE,CAAC;oBACtB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,4BAA4B;YAC5B,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;gBACtD,QAAQ,CAAC,QAAQ,CAAC,aAAa,SAAS,CAAC,MAAM,gBAAgB,WAAW,IAAI,IAAI,CAAC,MAAM,gBAAgB,CAAC,CAAC;YAC7G,CAAC;YAED,4BAA4B;YAC5B,MAAM,gBAAgB,GAA0B;gBAC9C,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,kBAAkB,EAAE,IAAI,CAAC,MAAM;gBAC/B,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG;gBAC3B,QAAQ;gBACR,SAAS;gBACT,MAAM;aACP,CAAC;YAEF,+DAA+D;YAC/D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtD,gBAAgB,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACjC,gBAAgB,CAAC,SAAS,GAAG,QAAQ,CAAC;gBACtC,gBAAgB,CAAC,YAAY,GAAG,YAAY,CAAC;gBAE7C,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;oBAChB,gBAAgB,CAAC,YAAY,GAAG,uBAAuB,QAAQ,KAAK,SAAS,qBAAqB,OAAO,CAAC,GAAG,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtI,CAAC;qBAAM,CAAC;oBACN,gBAAgB,CAAC,YAAY,GAAG,uBAAuB,QAAQ,KAAK,SAAS,qEAAqE,CAAC;gBACrJ,CAAC;gBAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC;gBACzC,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;gBAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;gBACnE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACvB,OAAO,CAAC,CAAC;YACX,CAAC;YAED,0CAA0C;YAC1C,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;YAEtD,kCAAkC;YAClC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;oBAClB,MAAM,CAAC,KAAK,CAAC,0BAA0B,OAAO,CAAC,MAAM,QAAQ,SAAS,CAAC,MAAM,SAAS,CAAC,CAAC;gBAC1F,CAAC;gBAED,qCAAqC;gBACrC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,SAAS,EAAE;oBAC/B,IAAI,EAAE,CAAC,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC;oBACrE,SAAS,EAAE,GAAG;oBACd,YAAY,EAAE,IAAI;oBAClB,UAAU,EAAE,IAAI;iBACjB,CAAC,CAAC;gBAEH,2BAA2B;gBAC3B,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAClD,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAErD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;oBAClB,MAAM,CAAC,KAAK,CAAC,eAAe,SAAS,CAAC,MAAM,qBAAqB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;gBACtF,CAAC;YACH,CAAC;YAED,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;YAEnE,2DAA2D;YAC3D,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACzB,CAAC;YAED,yDAAyD;YACzD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,IAAI,GAAa,EAAE,CAAC;gBAC1B,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAEzC,IAAI,SAAS,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;oBACpC,IAAI,CAAC,IAAI,CAAC,eAAe,UAAU,GAAG,CAAC,qBAAqB,CAAC,CAAC;gBAChE,CAAC;gBAED,wDAAwD;gBACxD,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;oBAC3D,IAAI,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;oBAC7C,IAAI,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;oBAC7C,IAAI,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;gBACrD,CAAC;gBAED,2BAA2B;gBAC3B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACpB,2DAA2D;oBAC3D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBACzC,CAAC;YACH,CAAC;YAED,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,gBAAgB,CAAC,GAAG,OAAO,CAAC;gBACrF,MAAM,CAAC,KAAK,CAAC,qDAAqD,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACpG,CAAC;YAED,OAAO,CAAC,CAAC,CAAC,UAAU;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,2CAA2C;YAC3C,gDAAgD;YAChD,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YACvC,OAAO,CAAC,CAAC,CAAC,QAAQ;QACpB,CAAC;IACH,CAAC;CACF","sourcesContent":["import { BaseCommand, BaseCommandOptions } from './BaseCommand.js';\nimport { getBuildFormatter } from '../formatters/index.js';\nimport Fuse from 'fuse.js';\nimport { Build } from '../types/index.js';\nimport { logger } from '../services/logger.js';\nimport { BuildFormatterOptions } from '../formatters/builds/Formatter.js';\nimport { Reporter } from '../ui/reporter.js';\n\nimport { Progress } from '../ui/progress.js';\n\nexport interface ViewerBuildsOptions extends BaseCommandOptions {\n count?: string;\n page?: string;\n org?: string;\n pipeline?: string;\n branch?: string;\n state?: string;\n tips?: boolean;\n}\n\nexport class ListBuilds extends BaseCommand {\n constructor(options?: Partial<ViewerBuildsOptions>) {\n super(options);\n }\n\n async execute(options: ViewerBuildsOptions): Promise<number> {\n await this.ensureInitialized();\n \n const executeStartTime = process.hrtime.bigint();\n if (options.debug) {\n logger.debug('Starting ViewerBuildsCommandHandler execution');\n }\n \n try {\n const format = options.format || 'plain';\n const reporter = new Reporter(format, options.quiet, options.tips);\n const viewerSpinner = Progress.spinner('Fetching viewer info...', { format });\n // First, get the current user's information using GraphQL\n const viewerData = await this.client.getViewer();\n viewerSpinner.stop();\n \n if (!viewerData?.viewer?.user?.uuid) {\n logger.error('Failed to get current user UUID information');\n return 1;\n }\n \n const userId = viewerData.viewer.user.uuid;\n const userName = viewerData.viewer.user.name || 'Current user';\n const userEmail = viewerData.viewer.user.email;\n \n // Use the REST API to get builds by the current user\n const perPage = options.count || '10';\n const page = options.page || '1';\n \n // If organization is not specified, we need to fetch organizations first\n let orgs: string[] = [];\n if (!options.org) {\n // Try to fetch the user's organizations\n try {\n orgs = await this.client.getViewerOrganizationSlugs();\n } catch (error) {\n logger.error(error as any, 'Failed to determine your organizations');\n return 1;\n }\n } else {\n orgs = [options.org];\n }\n \n // Initialize results array\n let allBuilds: Build[] = [];\n let accessErrors: string[] = [];\n \n // Use progress bar for multiple orgs, spinner for single org\n const useProgressBar = orgs.length > 1 && format === 'plain';\n const progress = useProgressBar ? Progress.bar({\n total: orgs.length,\n label: 'Fetching builds from organizations',\n format: format\n }) : null;\n \n // Create a spinner for single-org scenario\n let fetchSpinner = !useProgressBar ? Progress.spinner(undefined, { format }) : null;\n \n for (let i = 0; i < orgs.length; i++) {\n const org = orgs[i];\n \n try {\n if (progress) {\n progress.update(i, `Fetching builds from ${org}`);\n } else if (fetchSpinner) {\n fetchSpinner.update(`Fetching builds from ${org}…`, `Fetching builds from ${org}…`);\n }\n \n // First check if the user has access to this organization\n const hasAccess = await this.restClient.hasOrganizationAccess(org);\n if (!hasAccess) {\n accessErrors.push(`You don't have access to organization ${org}`);\n if (progress) {\n // Continue to next org with progress bar\n progress.update(i + 1, `No access to ${org}`);\n } else if (fetchSpinner) {\n fetchSpinner.fail(`No access to ${org}`);\n }\n continue;\n }\n \n const builds = await this.restClient.getBuilds(org, {\n creator: userId,\n pipeline: options.pipeline,\n branch: options.branch,\n state: options.state,\n per_page: perPage,\n page: page\n });\n \n if (options.debug) {\n logger.debug(`Received ${builds.length} builds from org ${org}`);\n }\n \n allBuilds = allBuilds.concat(builds);\n \n if (!progress && fetchSpinner) {\n fetchSpinner.stop();\n }\n } catch (error) {\n // Log unexpected errors but continue processing other orgs\n logger.error(error, `Error fetching builds for org ${org}`);\n if (!progress && fetchSpinner) {\n fetchSpinner.stop();\n }\n }\n }\n \n // Complete the progress bar\n if (progress) {\n const successOrgs = orgs.length - accessErrors.length;\n progress.complete(`Retrieved ${allBuilds.length} builds from ${successOrgs}/${orgs.length} organizations`);\n }\n \n // Prepare formatter options\n const formatterOptions: BuildFormatterOptions = {\n debug: options.debug,\n organizationsCount: orgs.length,\n orgSpecified: !!options.org,\n userName,\n userEmail,\n userId\n };\n \n // Handle the case where we have no builds due to access issues\n if (allBuilds.length === 0 && accessErrors.length > 0) {\n formatterOptions.hasError = true;\n formatterOptions.errorType = 'access';\n formatterOptions.accessErrors = accessErrors;\n \n if (options.org) {\n formatterOptions.errorMessage = `No builds found for ${userName} (${userEmail}) in organization ${options.org}. ${accessErrors[0]}`;\n } else {\n formatterOptions.errorMessage = `No builds found for ${userName} (${userEmail}). Try specifying an organization with --org to narrow your search.`;\n }\n \n const format = options.format || 'plain';\n const formatter = getBuildFormatter(format);\n const output = formatter.formatBuilds(allBuilds, formatterOptions);\n logger.console(output);\n return 1;\n }\n \n // Limit to the requested number of builds\n allBuilds = allBuilds.slice(0, parseInt(perPage, 10));\n \n // Apply fuzzy filter if specified\n if (options.filter) {\n if (options.debug) {\n logger.debug(`Applying fuzzy filter '${options.filter}' to ${allBuilds.length} builds`);\n }\n \n // Configure Fuse for fuzzy searching\n const fuse = new Fuse(allBuilds, {\n keys: ['pipeline.name', 'branch', 'message', 'creator.name', 'state'],\n threshold: 0.4,\n includeScore: true,\n shouldSort: true\n });\n \n // Perform the fuzzy search\n const searchResults = fuse.search(options.filter);\n allBuilds = searchResults.map(result => result.item);\n \n if (options.debug) {\n logger.debug(`Filtered to ${allBuilds.length} builds matching '${options.filter}'`);\n }\n }\n \n const formatter = getBuildFormatter(format);\n const output = formatter.formatBuilds(allBuilds, formatterOptions);\n \n // Output data directly to stdout to ensure proper ordering\n if (format === 'plain') {\n process.stdout.write(output + '\\n');\n } else {\n logger.console(output);\n }\n \n // Add contextual next-steps hints AFTER showing the data\n if (allBuilds.length > 0) {\n const tips: string[] = [];\n const buildCount = parseInt(perPage, 10);\n \n if (allBuilds.length === buildCount) {\n tips.push(`Use --count ${buildCount * 2} to see more builds`);\n }\n \n // If filtering is not active, suggest filtering options\n if (!options.state && !options.branch && !options.pipeline) {\n tips.push('Filter by state: --state failed');\n tips.push('Filter by branch: --branch main');\n tips.push('Filter by pipeline: --pipeline <name>');\n }\n \n // Display all tips at once\n if (tips.length > 0) {\n // Use individual style for consistency with current output\n tips.forEach(tip => reporter.tip(tip));\n }\n }\n \n if (options.debug) {\n const executeDuration = Number(process.hrtime.bigint() - executeStartTime) / 1000000;\n logger.debug(`ViewerBuildsCommandHandler execution completed in ${executeDuration.toFixed(2)}ms`);\n }\n \n return 0; // Success\n } catch (error) {\n // Only unexpected errors should reach here\n // Let the base command handle the error display\n this.handleError(error, options.debug);\n return 1; // Error\n }\n }\n}"]}
@@ -1,13 +1,17 @@
1
1
  import { BaseCommand } from './BaseCommand.js';
2
2
  import { logger } from '../services/logger.js';
3
3
  import { FormatterType } from '../formatters/index.js';
4
+ import { Progress } from '../ui/progress.js';
4
5
  export class ListOrganizations extends BaseCommand {
5
6
  constructor(options) {
6
7
  super(options);
7
8
  }
8
9
  async execute(options = {}) {
10
+ const format = options.format || 'plain';
11
+ const spinner = Progress.spinner('Fetching organizations…', { format });
9
12
  try {
10
13
  const organizations = await this.client.getOrganizations();
14
+ spinner.stop();
11
15
  if (options.debug) {
12
16
  logger.debug(`Fetched ${organizations.length} organizations`);
13
17
  }
@@ -16,9 +20,11 @@ export class ListOrganizations extends BaseCommand {
16
20
  // Format and output the organizations
17
21
  const output = formatter.formatOrganizations(organizations, { debug: options.debug });
18
22
  logger.console(output);
23
+ // Success is implicit - data display confirms retrieval
19
24
  return 0; // Success
20
25
  }
21
26
  catch (error) {
27
+ spinner.stop();
22
28
  this.handleError(error, options.debug);
23
29
  return 1; // Error
24
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ListOrganizations.js","sourceRoot":"/","sources":["commands/ListOrganizations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAyB,MAAM,wBAAwB,CAAC;AAK9E,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IAChD,YAAY,OAAsC;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,UAA+B,EAAE;QACpD,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAE3D,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,MAAM,CAAC,KAAK,CAAC,WAAW,aAAa,CAAC,MAAM,gBAAgB,CAAC,CAAC;YAChE,CAAC;YAED,gCAAgC;YAChC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,YAAY,EAAE,OAAO,CAA0B,CAAC;YAElG,sCAAsC;YACtC,MAAM,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;YACtF,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAEvB,OAAO,CAAC,CAAC,CAAC,UAAU;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YACvC,OAAO,CAAC,CAAC,CAAC,QAAQ;QACpB,CAAC;IACH,CAAC;CACF","sourcesContent":["import { BaseCommand, BaseCommandOptions } from './BaseCommand.js';\nimport { logger } from '../services/logger.js';\nimport { FormatterType, OrganizationFormatter } from '../formatters/index.js';\n\nexport interface OrganizationOptions extends BaseCommandOptions {\n}\n\nexport class ListOrganizations extends BaseCommand {\n constructor(options?: Partial<OrganizationOptions>) {\n super(options);\n }\n \n public async execute(options: OrganizationOptions = {}): Promise<number> { \n try {\n const organizations = await this.client.getOrganizations();\n \n if (options.debug) {\n logger.debug(`Fetched ${organizations.length} organizations`);\n }\n \n // Get the appropriate formatter\n const formatter = this.getFormatter(FormatterType.ORGANIZATION, options) as OrganizationFormatter;\n \n // Format and output the organizations\n const output = formatter.formatOrganizations(organizations, { debug: options.debug });\n logger.console(output);\n \n return 0; // Success\n } catch (error) {\n this.handleError(error, options.debug);\n return 1; // Error\n }\n }\n} "]}
1
+ {"version":3,"file":"ListOrganizations.js","sourceRoot":"/","sources":["commands/ListOrganizations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAyB,MAAM,wBAAwB,CAAC;AAE9E,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAK7C,MAAM,OAAO,iBAAkB,SAAQ,WAAW;IAChD,YAAY,OAAsC;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,UAA+B,EAAE;QACpD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC;QACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,yBAAyB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAExE,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAC3D,OAAO,CAAC,IAAI,EAAE,CAAC;YAEf,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,MAAM,CAAC,KAAK,CAAC,WAAW,aAAa,CAAC,MAAM,gBAAgB,CAAC,CAAC;YAChE,CAAC;YAED,gCAAgC;YAChC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,YAAY,EAAE,OAAO,CAA0B,CAAC;YAElG,sCAAsC;YACtC,MAAM,MAAM,GAAG,SAAS,CAAC,mBAAmB,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;YACtF,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACvB,wDAAwD;YAExD,OAAO,CAAC,CAAC,CAAC,UAAU;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YACvC,OAAO,CAAC,CAAC,CAAC,QAAQ;QACpB,CAAC;IACH,CAAC;CACF","sourcesContent":["import { BaseCommand, BaseCommandOptions } from './BaseCommand.js';\nimport { logger } from '../services/logger.js';\nimport { FormatterType, OrganizationFormatter } from '../formatters/index.js';\n\nimport { Progress } from '../ui/progress.js';\n\nexport interface OrganizationOptions extends BaseCommandOptions {\n}\n\nexport class ListOrganizations extends BaseCommand {\n constructor(options?: Partial<OrganizationOptions>) {\n super(options);\n }\n \n public async execute(options: OrganizationOptions = {}): Promise<number> { \n const format = options.format || 'plain';\n const spinner = Progress.spinner('Fetching organizations…', { format });\n \n try {\n const organizations = await this.client.getOrganizations();\n spinner.stop();\n \n if (options.debug) {\n logger.debug(`Fetched ${organizations.length} organizations`);\n }\n \n // Get the appropriate formatter\n const formatter = this.getFormatter(FormatterType.ORGANIZATION, options) as OrganizationFormatter;\n \n // Format and output the organizations\n const output = formatter.formatOrganizations(organizations, { debug: options.debug });\n logger.console(output);\n // Success is implicit - data display confirms retrieval\n \n return 0; // Success\n } catch (error) {\n spinner.stop();\n this.handleError(error, options.debug);\n return 1; // Error\n }\n }\n} "]}
@@ -2,8 +2,10 @@ import { BaseCommand } from './BaseCommand.js';
2
2
  import { getPipelineFormatter } from '../formatters/index.js';
3
3
  import Fuse from 'fuse.js';
4
4
  import { logger } from '../services/logger.js';
5
+ import { Progress } from '../ui/progress.js';
5
6
  export class ListPipelines extends BaseCommand {
6
- BATCH_SIZE = 500;
7
+ BATCH_SIZE = 50; // Reasonable batch size for API calls
8
+ DEFAULT_LIMIT = 50; // Default number of pipelines to show
7
9
  constructor(options) {
8
10
  super(options);
9
11
  }
@@ -25,6 +27,7 @@ export class ListPipelines extends BaseCommand {
25
27
  else {
26
28
  await this.listPipelines([org], options);
27
29
  }
30
+ // Success is implicit - data display confirms retrieval
28
31
  return 0; // Success
29
32
  }
30
33
  catch (error) {
@@ -34,14 +37,44 @@ export class ListPipelines extends BaseCommand {
34
37
  }
35
38
  async listPipelines(organizations, options) {
36
39
  let allPipelines = [];
37
- for (const org of organizations) {
40
+ let totalBeforeFilter = 0;
41
+ let hasMorePipelines = false; // Track if there are more pipelines available beyond what we fetched
42
+ // Use progress bar for multiple orgs, spinner for single org
43
+ const format = options.format || 'plain';
44
+ const useProgressBar = organizations.length > 1 && format === 'plain';
45
+ const orgProgress = useProgressBar ? Progress.bar({
46
+ total: organizations.length,
47
+ label: 'Processing organizations',
48
+ format: format
49
+ }) : null;
50
+ for (let orgIndex = 0; orgIndex < organizations.length; orgIndex++) {
51
+ const org = organizations[orgIndex];
52
+ // Use different progress indicators based on context
53
+ let spinner = null;
54
+ const pageProgress = useProgressBar ? Progress.spinner(`Loading pipelines from ${org}...`, { format }) : null;
55
+ if (!useProgressBar) {
56
+ // For single org, use spinner (existing behavior)
57
+ spinner = Progress.spinner(`Fetching pipelines from ${org}…`, { format });
58
+ }
38
59
  try {
39
60
  const batchSize = this.BATCH_SIZE;
40
61
  let hasNextPage = true;
41
62
  let cursor = null;
42
- const limitResults = options.count !== undefined;
43
- const resultLimit = limitResults ? parseInt(options.count, 10) : Infinity;
63
+ // Use default limit if no count specified
64
+ const resultLimit = options.count !== undefined
65
+ ? parseInt(options.count, 10)
66
+ : this.DEFAULT_LIMIT;
67
+ // Update org progress if using progress bar
68
+ if (orgProgress) {
69
+ orgProgress.update(orgIndex, `Organization: ${org}`);
70
+ }
71
+ let pageCount = 0;
72
+ let orgPipelineCount = 0;
44
73
  while (hasNextPage && allPipelines.length < resultLimit) {
74
+ pageCount++;
75
+ if (pageProgress) {
76
+ pageProgress.update(pageCount, `Loading ${org} (page ${pageCount})...`);
77
+ }
45
78
  if (options.debug) {
46
79
  logger.debug(`Fetching batch of pipelines from org ${org}, cursor: ${cursor || 'initial'}`);
47
80
  }
@@ -63,6 +96,7 @@ export class ListPipelines extends BaseCommand {
63
96
  organization: org
64
97
  };
65
98
  });
99
+ orgPipelineCount += pipelines.length;
66
100
  allPipelines = allPipelines.concat(pipelines);
67
101
  }
68
102
  // Check if we need to fetch more pages
@@ -74,21 +108,51 @@ export class ListPipelines extends BaseCommand {
74
108
  logger.debug(`More pages available, cursor: ${cursor}`);
75
109
  }
76
110
  }
77
- // If we're limiting results, stop after getting enough
78
- if (limitResults && allPipelines.length >= resultLimit) {
111
+ // Stop after getting enough results
112
+ if (allPipelines.length >= resultLimit) {
113
+ // If we hit the limit and there are more pages, remember that
114
+ if (hasNextPage) {
115
+ hasMorePipelines = true;
116
+ }
79
117
  break;
80
118
  }
81
119
  }
120
+ // Stop the appropriate progress indicator
121
+ if (pageProgress) {
122
+ pageProgress.stop();
123
+ if (options.debug) {
124
+ logger.debug(`Loaded ${orgPipelineCount} pipelines from ${org} in ${pageCount} pages`);
125
+ }
126
+ }
127
+ else if (spinner) {
128
+ spinner.stop();
129
+ }
82
130
  }
83
131
  catch (error) {
132
+ // Clean up any active progress indicators
133
+ if (spinner) {
134
+ spinner.stop();
135
+ }
136
+ if (pageProgress) {
137
+ pageProgress.stop();
138
+ }
84
139
  throw new Error(`Error fetching pipelines for organization ${org}`, { cause: error });
85
140
  }
86
141
  }
87
- // Apply limit if specified
88
- if (options.count) {
89
- const limit = parseInt(options.count, 10);
90
- allPipelines = allPipelines.slice(0, limit);
142
+ // Complete the org progress bar if used
143
+ if (orgProgress) {
144
+ orgProgress.complete(`Loaded ${allPipelines.length} pipelines from ${organizations.length} organizations`);
145
+ }
146
+ // Apply limit and track truncation
147
+ const requestedLimit = options.count
148
+ ? parseInt(options.count, 10)
149
+ : this.DEFAULT_LIMIT;
150
+ const truncated = allPipelines.length > requestedLimit;
151
+ if (allPipelines.length > requestedLimit) {
152
+ allPipelines = allPipelines.slice(0, requestedLimit);
91
153
  }
154
+ // Track total before filter for context
155
+ totalBeforeFilter = allPipelines.length;
92
156
  if (options.filter && allPipelines.length > 0) {
93
157
  if (options.debug) {
94
158
  logger.debug(`Applying fuzzy filter '${options.filter}' to ${allPipelines.length} pipelines`);
@@ -105,9 +169,20 @@ export class ListPipelines extends BaseCommand {
105
169
  logger.debug(`Filtered to ${allPipelines.length} pipelines matching '${options.filter}'`);
106
170
  }
107
171
  }
108
- const format = options.format || 'plain';
172
+ // Prepare formatter options with context
173
+ const formatterOptions = {
174
+ debug: options.debug,
175
+ filterActive: !!options.filter,
176
+ filterText: options.filter,
177
+ truncated: truncated || hasMorePipelines, // Either truncated locally or more available on server
178
+ hasMoreAvailable: hasMorePipelines,
179
+ totalBeforeFilter: totalBeforeFilter,
180
+ requestedLimit: requestedLimit,
181
+ organizationsCount: organizations.length,
182
+ orgSpecified: !!options.org
183
+ };
109
184
  const formatter = getPipelineFormatter(format);
110
- const output = formatter.formatPipelines(allPipelines, organizations);
185
+ const output = formatter.formatPipelines(allPipelines, organizations, formatterOptions);
111
186
  logger.console(output);
112
187
  }
113
188
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ListPipelines.js","sourceRoot":"/","sources":["commands/ListPipelines.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseCommand, BaseCommandOptions } from './BaseCommand.js';\nimport { getPipelineFormatter } from '../formatters/index.js';\nimport Fuse from 'fuse.js';\nimport { Pipeline } from '../types/index.js';\nimport { logger } from '../services/logger.js';\nexport interface PipelineOptions extends BaseCommandOptions {\n org?: string;\n count?: string;\n}\n\nexport class ListPipelines extends BaseCommand {\n readonly BATCH_SIZE = 500;\n \n constructor(options?: Partial<PipelineOptions>) {\n super(options);\n }\n \n async execute(options: PipelineOptions): Promise<number> {\n await this.ensureInitialized();\n \n try {\n // Need to get organization info if not provided\n const org = options.org;\n if (!org) {\n try {\n const orgs = await this.client.getViewerOrganizationSlugs();\n await this.listPipelines(orgs, options);\n } catch (error) {\n logger.error(error as any, 'Failed to determine your organizations');\n throw new Error('Failed to determine your organizations', { cause: error });\n }\n } else {\n await this.listPipelines([org], options);\n }\n \n return 0; // Success\n } catch (error) {\n this.handleError(error, options.debug);\n return 1; // Error\n }\n }\n \n private async listPipelines(organizations: string[], options: PipelineOptions): Promise<void> {\n let allPipelines: Pipeline[] = [];\n \n for (const org of organizations) {\n try {\n const batchSize = this.BATCH_SIZE;\n let hasNextPage = true;\n let cursor: string | null = null;\n const limitResults = options.count !== undefined;\n const resultLimit = limitResults ? parseInt(options.count as string, 10) : Infinity;\n \n while (hasNextPage && allPipelines.length < resultLimit) {\n if (options.debug) {\n logger.debug(`Fetching batch of pipelines from org ${org}, cursor: ${cursor || 'initial'}`);\n }\n \n const data = await this.client.getPipelines(org, batchSize, cursor || undefined);\n \n if (data?.organization?.pipelines?.edges) {\n // Add org information to each pipeline for display\n const pipelines = data.organization.pipelines.edges\n .filter(edge => edge !== null && edge.node !== null)\n .map(edge => {\n const node = edge!.node!;\n return {\n uuid: node.uuid || '',\n id: node.id || '',\n name: node.name || '',\n slug: node.slug || '',\n description: node.description,\n url: node.url || '',\n repository: node.repository,\n organization: org\n } as Pipeline;\n });\n \n allPipelines = allPipelines.concat(pipelines);\n }\n \n // Check if we need to fetch more pages\n hasNextPage = data?.organization?.pipelines?.pageInfo?.hasNextPage || false;\n cursor = data?.organization?.pipelines?.pageInfo?.endCursor || null;\n \n if (options.debug) {\n logger.debug(`Fetched batch of ${data?.organization?.pipelines?.edges?.length || 0} pipelines from org ${org}`);\n if (hasNextPage) {\n logger.debug(`More pages available, cursor: ${cursor}`);\n }\n }\n \n // If we're limiting results, stop after getting enough\n if (limitResults && allPipelines.length >= resultLimit) {\n break;\n }\n }\n } catch (error) {\n throw new Error(`Error fetching pipelines for organization ${org}`, { cause: error });\n }\n }\n \n // Apply limit if specified\n if (options.count) {\n const limit = parseInt(options.count, 10);\n allPipelines = allPipelines.slice(0, limit);\n }\n \n if (options.filter && allPipelines.length > 0) {\n if (options.debug) {\n logger.debug(`Applying fuzzy filter '${options.filter}' to ${allPipelines.length} pipelines`);\n }\n \n const fuse = new Fuse(allPipelines, {\n keys: ['name', 'slug', 'description'],\n threshold: 0.4,\n includeScore: true,\n shouldSort: true\n });\n \n const searchResults = fuse.search(options.filter);\n allPipelines = searchResults.map(result => result.item);\n \n if (options.debug) {\n logger.debug(`Filtered to ${allPipelines.length} pipelines matching '${options.filter}'`);\n }\n }\n \n const format = options.format || 'plain';\n const formatter = getPipelineFormatter(format);\n const output = formatter.formatPipelines(allPipelines, organizations);\n \n logger.console(output);\n }\n} "]}
1
+ {"version":3,"file":"ListPipelines.js","sourceRoot":"/","sources":["commands/ListPipelines.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseCommand, BaseCommandOptions } from './BaseCommand.js';\nimport { getPipelineFormatter } from '../formatters/index.js';\nimport { PipelineFormatterOptions } from '../formatters/pipelines/Formatter.js';\nimport Fuse from 'fuse.js';\nimport { Pipeline } from '../types/index.js';\nimport { logger } from '../services/logger.js';\n\nimport { Progress } from '../ui/progress.js';\nexport interface PipelineOptions extends BaseCommandOptions {\n org?: string;\n count?: string;\n filter?: string;\n}\n\nexport class ListPipelines extends BaseCommand {\n readonly BATCH_SIZE = 50; // Reasonable batch size for API calls\n readonly DEFAULT_LIMIT = 50; // Default number of pipelines to show\n \n constructor(options?: Partial<PipelineOptions>) {\n super(options);\n }\n \n async execute(options: PipelineOptions): Promise<number> {\n await this.ensureInitialized();\n \n try {\n\n // Need to get organization info if not provided\n const org = options.org;\n if (!org) {\n try {\n const orgs = await this.client.getViewerOrganizationSlugs();\n await this.listPipelines(orgs, options);\n } catch (error) {\n logger.error(error as any, 'Failed to determine your organizations');\n throw new Error('Failed to determine your organizations', { cause: error });\n }\n } else {\n await this.listPipelines([org], options);\n }\n \n // Success is implicit - data display confirms retrieval\n return 0; // Success\n } catch (error) {\n this.handleError(error, options.debug);\n return 1; // Error\n }\n }\n \n private async listPipelines(organizations: string[], options: PipelineOptions): Promise<void> {\n let allPipelines: Pipeline[] = [];\n let totalBeforeFilter = 0;\n let hasMorePipelines = false; // Track if there are more pipelines available beyond what we fetched\n \n // Use progress bar for multiple orgs, spinner for single org\n const format = options.format || 'plain';\n const useProgressBar = organizations.length > 1 && format === 'plain';\n const orgProgress = useProgressBar ? Progress.bar({\n total: organizations.length,\n label: 'Processing organizations',\n format: format\n }) : null;\n \n for (let orgIndex = 0; orgIndex < organizations.length; orgIndex++) {\n const org = organizations[orgIndex];\n \n // Use different progress indicators based on context\n let spinner = null;\n const pageProgress = useProgressBar ? Progress.spinner(\n `Loading pipelines from ${org}...`,\n { format }\n ) : null;\n \n if (!useProgressBar) {\n // For single org, use spinner (existing behavior)\n spinner = Progress.spinner(`Fetching pipelines from ${org}…`, { format });\n }\n \n try {\n const batchSize = this.BATCH_SIZE;\n let hasNextPage = true;\n let cursor: string | null = null;\n // Use default limit if no count specified\n const resultLimit = options.count !== undefined \n ? parseInt(options.count as string, 10) \n : this.DEFAULT_LIMIT;\n \n // Update org progress if using progress bar\n if (orgProgress) {\n orgProgress.update(orgIndex, `Organization: ${org}`);\n }\n \n let pageCount = 0;\n let orgPipelineCount = 0;\n \n while (hasNextPage && allPipelines.length < resultLimit) {\n pageCount++;\n \n if (pageProgress) {\n pageProgress.update(pageCount, `Loading ${org} (page ${pageCount})...`);\n }\n \n if (options.debug) {\n logger.debug(`Fetching batch of pipelines from org ${org}, cursor: ${cursor || 'initial'}`);\n }\n \n const data = await this.client.getPipelines(org, batchSize, cursor || undefined);\n \n if (data?.organization?.pipelines?.edges) {\n // Add org information to each pipeline for display\n const pipelines = data.organization.pipelines.edges\n .filter(edge => edge !== null && edge.node !== null)\n .map(edge => {\n const node = edge!.node!;\n return {\n uuid: node.uuid || '',\n id: node.id || '',\n name: node.name || '',\n slug: node.slug || '',\n description: node.description,\n url: node.url || '',\n repository: node.repository,\n organization: org\n } as Pipeline;\n });\n \n orgPipelineCount += pipelines.length;\n allPipelines = allPipelines.concat(pipelines);\n }\n \n // Check if we need to fetch more pages\n hasNextPage = data?.organization?.pipelines?.pageInfo?.hasNextPage || false;\n cursor = data?.organization?.pipelines?.pageInfo?.endCursor || null;\n \n if (options.debug) {\n logger.debug(`Fetched batch of ${data?.organization?.pipelines?.edges?.length || 0} pipelines from org ${org}`);\n if (hasNextPage) {\n logger.debug(`More pages available, cursor: ${cursor}`);\n }\n }\n \n // Stop after getting enough results\n if (allPipelines.length >= resultLimit) {\n // If we hit the limit and there are more pages, remember that\n if (hasNextPage) {\n hasMorePipelines = true;\n }\n break;\n }\n }\n \n // Stop the appropriate progress indicator\n if (pageProgress) {\n pageProgress.stop();\n if (options.debug) {\n logger.debug(`Loaded ${orgPipelineCount} pipelines from ${org} in ${pageCount} pages`);\n }\n } else if (spinner) {\n spinner.stop();\n }\n } catch (error) {\n // Clean up any active progress indicators \n if (spinner) {\n spinner.stop();\n }\n if (pageProgress) {\n pageProgress.stop();\n }\n throw new Error(`Error fetching pipelines for organization ${org}`, { cause: error });\n }\n }\n \n // Complete the org progress bar if used\n if (orgProgress) {\n orgProgress.complete(`Loaded ${allPipelines.length} pipelines from ${organizations.length} organizations`);\n }\n \n // Apply limit and track truncation\n const requestedLimit = options.count \n ? parseInt(options.count, 10) \n : this.DEFAULT_LIMIT;\n \n const truncated = allPipelines.length > requestedLimit;\n \n if (allPipelines.length > requestedLimit) {\n allPipelines = allPipelines.slice(0, requestedLimit);\n }\n \n // Track total before filter for context\n totalBeforeFilter = allPipelines.length;\n \n if (options.filter && allPipelines.length > 0) {\n if (options.debug) {\n logger.debug(`Applying fuzzy filter '${options.filter}' to ${allPipelines.length} pipelines`);\n }\n \n const fuse = new Fuse(allPipelines, {\n keys: ['name', 'slug', 'description'],\n threshold: 0.4,\n includeScore: true,\n shouldSort: true\n });\n \n const searchResults = fuse.search(options.filter);\n allPipelines = searchResults.map(result => result.item);\n \n if (options.debug) {\n logger.debug(`Filtered to ${allPipelines.length} pipelines matching '${options.filter}'`);\n }\n }\n \n // Prepare formatter options with context\n const formatterOptions: PipelineFormatterOptions = {\n debug: options.debug,\n filterActive: !!options.filter,\n filterText: options.filter,\n truncated: truncated || hasMorePipelines, // Either truncated locally or more available on server\n hasMoreAvailable: hasMorePipelines,\n totalBeforeFilter: totalBeforeFilter,\n requestedLimit: requestedLimit,\n organizationsCount: organizations.length,\n orgSpecified: !!options.org\n };\n \n const formatter = getPipelineFormatter(format);\n const output = formatter.formatPipelines(allPipelines, organizations, formatterOptions);\n \n logger.console(output);\n }\n} "]}
@@ -2,11 +2,15 @@ import { BaseCommand } from './BaseCommand.js';
2
2
  import { logger } from '../services/logger.js';
3
3
  import prompts from 'prompts';
4
4
  import { FormatterFactory, FormatterType } from '../formatters/FormatterFactory.js';
5
+ import { isRunningInAlfred } from '../utils/alfred.js';
6
+ import { Reporter } from '../ui/reporter.js';
5
7
  export class ManageToken extends BaseCommand {
6
8
  formatter;
9
+ reporter;
7
10
  constructor(options) {
8
11
  super(options);
9
12
  this.formatter = FormatterFactory.getFormatter(FormatterType.TOKEN, options?.format);
13
+ this.reporter = new Reporter(options?.format || 'plain', options?.quiet, options?.tips);
10
14
  }
11
15
  static get requiresToken() {
12
16
  return false;
@@ -18,6 +22,12 @@ export class ManageToken extends BaseCommand {
18
22
  if (options.store) {
19
23
  const { success, errors } = await this.storeToken();
20
24
  if (success) {
25
+ // Add next-steps hints after successful token storage (no redundant success message)
26
+ this.reporter.tips([
27
+ 'Verify access with: bktide token --check',
28
+ 'Explore your organizations: bktide orgs',
29
+ 'List pipelines: bktide pipelines'
30
+ ]);
21
31
  return 0;
22
32
  }
23
33
  else {
@@ -30,7 +40,7 @@ export class ManageToken extends BaseCommand {
30
40
  await this.resetToken();
31
41
  }
32
42
  else if (options.check) {
33
- const { errors } = await this.checkToken();
43
+ const { errors } = await this.checkToken({ format: options.format });
34
44
  if (errors.length > 0) {
35
45
  const formattedErrors = this.formatter.formatAuthErrors('validating', errors);
36
46
  logger.console(formattedErrors);
@@ -38,7 +48,7 @@ export class ManageToken extends BaseCommand {
38
48
  }
39
49
  }
40
50
  else {
41
- const { errors } = await this.checkOrStoreToken();
51
+ const { errors } = await this.checkOrStoreToken({ format: options.format });
42
52
  if (errors.length > 0) {
43
53
  const formattedErrors = this.formatter.formatAuthErrors('checking or storing', errors);
44
54
  logger.console(formattedErrors);
@@ -61,6 +71,9 @@ export class ManageToken extends BaseCommand {
61
71
  tokenToStore = this.options.token;
62
72
  }
63
73
  else {
74
+ if (isRunningInAlfred()) {
75
+ return { success: false, errors: [new Error('In Alfred, set token via Workflow Configuration.')] };
76
+ }
64
77
  // Otherwise prompt the user
65
78
  const response = await prompts({
66
79
  type: 'password',
@@ -79,7 +92,9 @@ export class ManageToken extends BaseCommand {
79
92
  return { success: false, errors: [new Error('No token provided')] };
80
93
  }
81
94
  // Validate the token using the CredentialManager
82
- const validationResult = await BaseCommand.credentialManager.validateToken(tokenToStore);
95
+ const validationResult = await BaseCommand.credentialManager.validateToken(tokenToStore, {
96
+ showProgress: true // Show progress when validating during store
97
+ });
83
98
  if (!validationResult.canListOrganizations) {
84
99
  throw new Error('Token is invalid or does not have access to list organizations');
85
100
  }
@@ -121,8 +136,8 @@ export class ManageToken extends BaseCommand {
121
136
  logger.console(formattedError);
122
137
  }
123
138
  }
124
- async checkOrStoreToken() {
125
- const { status, errors } = await this.checkToken();
139
+ async checkOrStoreToken(options) {
140
+ const { status, errors } = await this.checkToken(options);
126
141
  if (!status.hasToken || !status.isValid) {
127
142
  const { success, errors: storeErrors } = await this.storeToken();
128
143
  if (success) {
@@ -134,8 +149,11 @@ export class ManageToken extends BaseCommand {
134
149
  }
135
150
  return { stored: false, errors };
136
151
  }
137
- async checkToken() {
138
- const hasToken = await BaseCommand.credentialManager.hasToken();
152
+ async checkToken(options) {
153
+ // In Alfred, check presence of env var as token existence
154
+ const hasToken = isRunningInAlfred()
155
+ ? Boolean(process.env.BUILDKITE_API_TOKEN || process.env.BK_TOKEN)
156
+ : await BaseCommand.credentialManager.hasToken();
139
157
  let isValid = false;
140
158
  let validation = {
141
159
  valid: false,
@@ -145,7 +163,9 @@ export class ManageToken extends BaseCommand {
145
163
  const errors = [];
146
164
  if (hasToken) {
147
165
  // Get the token for validation
148
- const token = await BaseCommand.credentialManager.getToken();
166
+ const token = isRunningInAlfred()
167
+ ? (process.env.BUILDKITE_API_TOKEN || process.env.BK_TOKEN)
168
+ : await BaseCommand.credentialManager.getToken();
149
169
  if (!token) {
150
170
  const tokenStatus = {
151
171
  hasToken: false,
@@ -160,7 +180,10 @@ export class ManageToken extends BaseCommand {
160
180
  }
161
181
  // Validate the token using the CredentialManager
162
182
  try {
163
- validation = await BaseCommand.credentialManager.validateToken(token);
183
+ validation = await BaseCommand.credentialManager.validateToken(token, {
184
+ format: options?.format,
185
+ showProgress: false // Don't show progress since we're showing formatted output
186
+ });
164
187
  isValid = validation.valid && validation.canListOrganizations;
165
188
  }
166
189
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"ManageToken.js","sourceRoot":"/","sources":["commands/ManageToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAWpF,MAAM,OAAO,WAAY,SAAQ,WAAW;IAClC,SAAS,CAAiB;IAElC,YAAY,OAA+B;QACzC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,SAAS,GAAG,gBAAgB,CAAC,YAAY,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAmB,CAAC;IACzG,CAAC;IAED,MAAM,KAAK,aAAa;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAqB;QACjC,IAAI,CAAC;YACH,+DAA+D;YAC/D,6DAA6D;YAE7D,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;gBACpD,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,CAAC,CAAC;gBACX,CAAC;qBAAM,CAAC;oBACN,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;oBAC3E,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;oBAChC,OAAO,CAAC,CAAC;gBACX,CAAC;YACH,CAAC;iBAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBACzB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1B,CAAC;iBAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBACzB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;gBAC3C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtB,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;oBAC9E,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;oBAChC,OAAO,CAAC,CAAC;gBACX,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAClD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtB,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;oBACvF,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;oBAChC,OAAO,CAAC,CAAC;gBACX,CAAC;YACH,CAAC;YAED,OAAO,CAAC,CAAC,CAAC,UAAU;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YACtE,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAC/B,OAAO,CAAC,CAAC,CAAC,QAAQ;QACpB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,IAAI,CAAC;YACH,IAAI,YAAgC,CAAC;YAErC,0CAA0C;YAC1C,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBACvB,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACN,4BAA4B;gBAC5B,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;oBAC7B,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,iCAAiC;oBAC1C,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,4BAA4B;iBAC1E,CAAC,CAAC;gBAEH,8CAA8C;gBAC9C,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;oBACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC,EAAE,CAAC;gBAC5E,CAAC;gBAED,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC;YAChC,CAAC;YAED,iDAAiD;YACjD,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC;YACtE,CAAC;YAED,iDAAiD;YACjD,MAAM,gBAAgB,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;YAEzF,IAAI,CAAC,gBAAgB,CAAC,oBAAoB,EAAE,CAAC;gBAC3C,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;YACpF,CAAC;YAED,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;gBAC5B,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,aAAa,CAAC;qBAC/D,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;qBACnF,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE;oBACrB,MAAM,WAAW,GAAG,EAAE,CAAC;oBACvB,IAAI,CAAC,MAAM,CAAC,OAAO;wBAAE,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACjD,IAAI,CAAC,MAAM,CAAC,MAAM;wBAAE,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBAC/C,IAAI,CAAC,MAAM,CAAC,aAAa;wBAAE,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;oBAC7D,OAAO,GAAG,GAAG,KAAK,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;gBAC9C,CAAC,CAAC,CAAC;gBACL,MAAM,IAAI,KAAK,CAAC,mDAAmD,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC/F,CAAC;YAED,gCAAgC;YAChC,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YAE5E,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7C,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;YAChE,IAAI,OAAO,GAAG,KAAK,CAAC;YAEpB,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,WAAW,EAAE,CAAC;YAC9D,CAAC;YAED,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,sBAAsB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YACjF,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YACtE,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,iBAAiB;QAC7B,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACxC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACjE,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;YAChD,CAAC;QACH,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;QAChE,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,UAAU,GAA0B;YACtC,KAAK,EAAE,KAAK;YACZ,oBAAoB,EAAE,KAAK;YAC3B,aAAa,EAAE,EAAE;SAClB,CAAC;QACF,MAAM,MAAM,GAAc,EAAE,CAAC;QAE7B,IAAI,QAAQ,EAAE,CAAC;YACb,+BAA+B;YAC/B,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;YAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,WAAW,GAAgB;oBAC/B,QAAQ,EAAE,KAAK;oBACf,OAAO,EAAE,KAAK;oBACd,UAAU,EAAE;wBACV,KAAK,EAAE,KAAK;wBACZ,oBAAoB,EAAE,KAAK;wBAC3B,aAAa,EAAE,EAAE;qBAClB;iBACF,CAAC;gBACF,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;YACzC,CAAC;YAED,iDAAiD;YACjD,IAAI,CAAC;gBACH,UAAU,GAAG,MAAM,WAAW,CAAC,iBAAiB,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;gBACtE,OAAO,GAAG,UAAU,CAAC,KAAK,IAAI,UAAU,CAAC,oBAAoB,CAAC;YAChE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GAAgB;YAC/B,QAAQ;YACR,OAAO;YACP,UAAU;SACX,CAAC;QAEF,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACtE,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAEhC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IACzC,CAAC;CACF","sourcesContent":["import { BaseCommand, BaseCommandOptions } from './BaseCommand.js';\nimport { logger } from '../services/logger.js';\nimport prompts from 'prompts';\nimport { FormatterFactory, FormatterType } from '../formatters/FormatterFactory.js';\nimport { TokenFormatter } from '../formatters/token/Formatter.js';\nimport { TokenStatus, TokenValidationStatus, TokenCheckResult, TokenCheckOrStoreResult, TokenStoreResult } from '../types/credentials.js';\n\nexport interface TokenOptions extends BaseCommandOptions {\n check?: boolean;\n store?: boolean;\n reset?: boolean;\n token?: string;\n}\n\nexport class ManageToken extends BaseCommand {\n private formatter: TokenFormatter;\n\n constructor(options?: Partial<TokenOptions>) {\n super(options);\n this.formatter = FormatterFactory.getFormatter(FormatterType.TOKEN, options?.format) as TokenFormatter;\n }\n\n static get requiresToken(): boolean {\n return false;\n }\n\n async execute(options: TokenOptions): Promise<number> {\n try {\n // Handle option priorities: if multiple options are provided, \n // we'll process them in this priority: store > reset > check\n \n if (options.store) {\n const { success, errors } = await this.storeToken();\n if (success) {\n return 0;\n } else {\n const formattedErrors = this.formatter.formatAuthErrors('storing', errors);\n logger.console(formattedErrors);\n return 1;\n }\n } else if (options.reset) {\n await this.resetToken();\n } else if (options.check) {\n const { errors } = await this.checkToken();\n if (errors.length > 0) {\n const formattedErrors = this.formatter.formatAuthErrors('validating', errors);\n logger.console(formattedErrors);\n return 0;\n }\n } else {\n const { errors } = await this.checkOrStoreToken();\n if (errors.length > 0) {\n const formattedErrors = this.formatter.formatAuthErrors('checking or storing', errors);\n logger.console(formattedErrors);\n return 0;\n }\n }\n \n return 0; // Success\n } catch (error) {\n const formattedError = this.formatter.formatError('executing', error);\n logger.console(formattedError);\n return 1; // Error\n }\n }\n\n private async storeToken(): Promise<TokenStoreResult> {\n try {\n let tokenToStore: string | undefined;\n\n // If token is provided in options, use it\n if (this.options.token) {\n tokenToStore = this.options.token;\n } else {\n // Otherwise prompt the user\n const response = await prompts({\n type: 'password',\n name: 'token',\n message: 'Enter your Buildkite API token:',\n validate: value => value.length > 0 ? true : 'Please enter a valid token'\n });\n \n // Check if user cancelled the prompt (Ctrl+C)\n if (!response.token) {\n return { success: false, errors: [new Error('Token storage cancelled')] };\n }\n \n tokenToStore = response.token;\n }\n\n // Ensure we have a valid token before proceeding\n if (!tokenToStore) {\n return { success: false, errors: [new Error('No token provided')] };\n }\n \n // Validate the token using the CredentialManager\n const validationResult = await BaseCommand.credentialManager.validateToken(tokenToStore);\n \n if (!validationResult.canListOrganizations) {\n throw new Error('Token is invalid or does not have access to list organizations');\n }\n\n if (!validationResult.valid) {\n const invalidOrgs = Object.entries(validationResult.organizations)\n .filter(([_, status]) => !status.graphql || !status.builds || !status.organizations)\n .map(([org, status]) => {\n const invalidApis = [];\n if (!status.graphql) invalidApis.push('GraphQL');\n if (!status.builds) invalidApis.push('Builds');\n if (!status.organizations) invalidApis.push('Organizations');\n return `${org} (${invalidApis.join(', ')})`;\n });\n throw new Error(`Token has limited access in some organizations: ${invalidOrgs.join(', ')}`);\n }\n \n // Store the token if it's valid\n const success = await BaseCommand.credentialManager.saveToken(tokenToStore);\n \n return { success, errors: [] };\n } catch (error) {\n return { success: false, errors: [error] };\n }\n }\n\n private async resetToken(): Promise<void> {\n try {\n const hadToken = await BaseCommand.credentialManager.hasToken();\n let success = false;\n \n if (hadToken) {\n success = await BaseCommand.credentialManager.deleteToken();\n }\n \n const formattedResult = this.formatter.formatTokenResetResult(success, hadToken);\n logger.console(formattedResult);\n } catch (error) {\n const formattedError = this.formatter.formatError('resetting', error);\n logger.console(formattedError);\n }\n }\n\n private async checkOrStoreToken(): Promise<TokenCheckOrStoreResult> {\n const { status, errors } = await this.checkToken();\n if (!status.hasToken || !status.isValid) {\n const { success, errors: storeErrors } = await this.storeToken();\n if (success) {\n return { stored: true, errors: [] };\n } else {\n return { stored: false, errors: storeErrors };\n }\n }\n return { stored: false, errors };\n }\n\n private async checkToken(): Promise<TokenCheckResult> {\n const hasToken = await BaseCommand.credentialManager.hasToken();\n let isValid = false;\n let validation: TokenValidationStatus = { \n valid: false, \n canListOrganizations: false,\n organizations: {} \n };\n const errors: unknown[] = [];\n\n if (hasToken) {\n // Get the token for validation\n const token = await BaseCommand.credentialManager.getToken();\n if (!token) {\n const tokenStatus: TokenStatus = {\n hasToken: false,\n isValid: false,\n validation: { \n valid: false, \n canListOrganizations: false,\n organizations: {} \n }\n };\n return { status: tokenStatus, errors };\n }\n\n // Validate the token using the CredentialManager\n try {\n validation = await BaseCommand.credentialManager.validateToken(token);\n isValid = validation.valid && validation.canListOrganizations;\n } catch (error) {\n errors.push(error);\n }\n }\n \n const tokenStatus: TokenStatus = {\n hasToken,\n isValid,\n validation\n };\n \n const formattedResult = this.formatter.formatTokenStatus(tokenStatus);\n logger.console(formattedResult);\n \n return { status: tokenStatus, errors };\n }\n} "]}
1
+ {"version":3,"file":"ManageToken.js","sourceRoot":"/","sources":["commands/ManageToken.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseCommand, BaseCommandOptions } from './BaseCommand.js';\nimport { logger } from '../services/logger.js';\nimport prompts from 'prompts';\nimport { FormatterFactory, FormatterType } from '../formatters/FormatterFactory.js';\nimport { TokenFormatter } from '../formatters/token/Formatter.js';\nimport { TokenStatus, TokenValidationStatus, TokenCheckResult, TokenCheckOrStoreResult, TokenStoreResult } from '../types/credentials.js';\nimport { isRunningInAlfred } from '../utils/alfred.js';\nimport { Reporter } from '../ui/reporter.js';\n\nexport interface TokenOptions extends BaseCommandOptions {\n check?: boolean;\n store?: boolean;\n reset?: boolean;\n token?: string;\n tips?: boolean;\n}\n\nexport class ManageToken extends BaseCommand {\n private formatter: TokenFormatter;\n private reporter: Reporter;\n\n constructor(options?: Partial<TokenOptions>) {\n super(options);\n this.formatter = FormatterFactory.getFormatter(FormatterType.TOKEN, options?.format) as TokenFormatter;\n this.reporter = new Reporter(options?.format || 'plain', options?.quiet, options?.tips);\n }\n\n static get requiresToken(): boolean {\n return false;\n }\n\n async execute(options: TokenOptions): Promise<number> {\n try {\n // Handle option priorities: if multiple options are provided, \n // we'll process them in this priority: store > reset > check\n \n if (options.store) {\n const { success, errors } = await this.storeToken();\n if (success) {\n // Add next-steps hints after successful token storage (no redundant success message)\n this.reporter.tips([\n 'Verify access with: bktide token --check',\n 'Explore your organizations: bktide orgs',\n 'List pipelines: bktide pipelines'\n ]);\n return 0;\n } else {\n const formattedErrors = this.formatter.formatAuthErrors('storing', errors);\n logger.console(formattedErrors);\n return 1;\n }\n } else if (options.reset) {\n await this.resetToken();\n } else if (options.check) {\n const { errors } = await this.checkToken({ format: options.format });\n if (errors.length > 0) {\n const formattedErrors = this.formatter.formatAuthErrors('validating', errors);\n logger.console(formattedErrors);\n return 0;\n }\n } else {\n const { errors } = await this.checkOrStoreToken({ format: options.format });\n if (errors.length > 0) {\n const formattedErrors = this.formatter.formatAuthErrors('checking or storing', errors);\n logger.console(formattedErrors);\n return 0;\n }\n }\n \n return 0; // Success\n } catch (error) {\n const formattedError = this.formatter.formatError('executing', error);\n logger.console(formattedError);\n return 1; // Error\n }\n }\n\n private async storeToken(): Promise<TokenStoreResult> {\n try {\n let tokenToStore: string | undefined;\n\n // If token is provided in options, use it\n if (this.options.token) {\n tokenToStore = this.options.token;\n } else {\n if (isRunningInAlfred()) {\n return { success: false, errors: [new Error('In Alfred, set token via Workflow Configuration.')] };\n }\n // Otherwise prompt the user\n const response = await prompts({\n type: 'password',\n name: 'token',\n message: 'Enter your Buildkite API token:',\n validate: value => value.length > 0 ? true : 'Please enter a valid token'\n });\n \n // Check if user cancelled the prompt (Ctrl+C)\n if (!response.token) {\n return { success: false, errors: [new Error('Token storage cancelled')] };\n }\n \n tokenToStore = response.token;\n }\n\n // Ensure we have a valid token before proceeding\n if (!tokenToStore) {\n return { success: false, errors: [new Error('No token provided')] };\n }\n \n // Validate the token using the CredentialManager\n const validationResult = await BaseCommand.credentialManager.validateToken(tokenToStore, {\n showProgress: true // Show progress when validating during store\n });\n \n if (!validationResult.canListOrganizations) {\n throw new Error('Token is invalid or does not have access to list organizations');\n }\n\n if (!validationResult.valid) {\n const invalidOrgs = Object.entries(validationResult.organizations)\n .filter(([_, status]) => !status.graphql || !status.builds || !status.organizations)\n .map(([org, status]) => {\n const invalidApis = [];\n if (!status.graphql) invalidApis.push('GraphQL');\n if (!status.builds) invalidApis.push('Builds');\n if (!status.organizations) invalidApis.push('Organizations');\n return `${org} (${invalidApis.join(', ')})`;\n });\n throw new Error(`Token has limited access in some organizations: ${invalidOrgs.join(', ')}`);\n }\n \n // Store the token if it's valid\n const success = await BaseCommand.credentialManager.saveToken(tokenToStore);\n \n return { success, errors: [] };\n } catch (error) {\n return { success: false, errors: [error] };\n }\n }\n\n private async resetToken(): Promise<void> {\n try {\n const hadToken = await BaseCommand.credentialManager.hasToken();\n let success = false;\n \n if (hadToken) {\n success = await BaseCommand.credentialManager.deleteToken();\n }\n \n const formattedResult = this.formatter.formatTokenResetResult(success, hadToken);\n logger.console(formattedResult);\n } catch (error) {\n const formattedError = this.formatter.formatError('resetting', error);\n logger.console(formattedError);\n }\n }\n\n private async checkOrStoreToken(options?: { format?: string }): Promise<TokenCheckOrStoreResult> {\n const { status, errors } = await this.checkToken(options);\n if (!status.hasToken || !status.isValid) {\n const { success, errors: storeErrors } = await this.storeToken();\n if (success) {\n return { stored: true, errors: [] };\n } else {\n return { stored: false, errors: storeErrors };\n }\n }\n return { stored: false, errors };\n }\n\n private async checkToken(options?: { format?: string }): Promise<TokenCheckResult> {\n // In Alfred, check presence of env var as token existence\n const hasToken = isRunningInAlfred()\n ? Boolean(process.env.BUILDKITE_API_TOKEN || process.env.BK_TOKEN)\n : await BaseCommand.credentialManager.hasToken();\n let isValid = false;\n let validation: TokenValidationStatus = { \n valid: false, \n canListOrganizations: false,\n organizations: {} \n };\n const errors: unknown[] = [];\n\n if (hasToken) {\n // Get the token for validation\n const token = isRunningInAlfred()\n ? (process.env.BUILDKITE_API_TOKEN || process.env.BK_TOKEN)\n : await BaseCommand.credentialManager.getToken();\n if (!token) {\n const tokenStatus: TokenStatus = {\n hasToken: false,\n isValid: false,\n validation: { \n valid: false, \n canListOrganizations: false,\n organizations: {} \n }\n };\n return { status: tokenStatus, errors };\n }\n\n // Validate the token using the CredentialManager\n try {\n validation = await BaseCommand.credentialManager.validateToken(token, {\n format: options?.format,\n showProgress: false // Don't show progress since we're showing formatted output\n });\n isValid = validation.valid && validation.canListOrganizations;\n } catch (error) {\n errors.push(error);\n }\n }\n \n const tokenStatus: TokenStatus = {\n hasToken,\n isValid,\n validation\n };\n \n const formattedResult = this.formatter.formatTokenStatus(tokenStatus);\n logger.console(formattedResult);\n \n return { status: tokenStatus, errors };\n }\n} "]}