bktide 0.0.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.
Files changed (160) hide show
  1. package/README.md +145 -0
  2. package/WORKFLOW_README.md +65 -0
  3. package/bin/alfred-entrypoint +54 -0
  4. package/dist/commands/BaseCommand.js +159 -0
  5. package/dist/commands/BaseCommand.js.map +1 -0
  6. package/dist/commands/BaseCommandHandler.js +80 -0
  7. package/dist/commands/BaseCommandHandler.js.map +1 -0
  8. package/dist/commands/BuildCommandHandler.js +28 -0
  9. package/dist/commands/BuildCommandHandler.js.map +1 -0
  10. package/dist/commands/HelloCommandHandler.js +6 -0
  11. package/dist/commands/HelloCommandHandler.js.map +1 -0
  12. package/dist/commands/ListAnnotations.js +60 -0
  13. package/dist/commands/ListAnnotations.js.map +1 -0
  14. package/dist/commands/ListBuilds.js +137 -0
  15. package/dist/commands/ListBuilds.js.map +1 -0
  16. package/dist/commands/ListOrganizations.js +27 -0
  17. package/dist/commands/ListOrganizations.js.map +1 -0
  18. package/dist/commands/ListPipelines.js +114 -0
  19. package/dist/commands/ListPipelines.js.map +1 -0
  20. package/dist/commands/ManageToken.js +180 -0
  21. package/dist/commands/ManageToken.js.map +1 -0
  22. package/dist/commands/OrganizationCommandHandler.js +53 -0
  23. package/dist/commands/OrganizationCommandHandler.js.map +1 -0
  24. package/dist/commands/PipelineCommandHandler.js +142 -0
  25. package/dist/commands/PipelineCommandHandler.js.map +1 -0
  26. package/dist/commands/ShowViewer.js +26 -0
  27. package/dist/commands/ShowViewer.js.map +1 -0
  28. package/dist/commands/UserBuildsCommandHandler.js +61 -0
  29. package/dist/commands/UserBuildsCommandHandler.js.map +1 -0
  30. package/dist/commands/ViewerBuildsCommandHandler.js +176 -0
  31. package/dist/commands/ViewerBuildsCommandHandler.js.map +1 -0
  32. package/dist/commands/ViewerCommandHandler.js +46 -0
  33. package/dist/commands/ViewerCommandHandler.js.map +1 -0
  34. package/dist/commands/index.js +8 -0
  35. package/dist/commands/index.js.map +1 -0
  36. package/dist/formatters/BaseFormatter.js +14 -0
  37. package/dist/formatters/BaseFormatter.js.map +1 -0
  38. package/dist/formatters/FormatterFactory.js +48 -0
  39. package/dist/formatters/FormatterFactory.js.map +1 -0
  40. package/dist/formatters/annotations/Formatter.js +10 -0
  41. package/dist/formatters/annotations/Formatter.js.map +1 -0
  42. package/dist/formatters/annotations/JsonFormatter.js +20 -0
  43. package/dist/formatters/annotations/JsonFormatter.js.map +1 -0
  44. package/dist/formatters/annotations/PlainTextFormatter.js +35 -0
  45. package/dist/formatters/annotations/PlainTextFormatter.js.map +1 -0
  46. package/dist/formatters/annotations/index.js +23 -0
  47. package/dist/formatters/annotations/index.js.map +1 -0
  48. package/dist/formatters/builds/AlfredFormatter.js +135 -0
  49. package/dist/formatters/builds/AlfredFormatter.js.map +1 -0
  50. package/dist/formatters/builds/Formatter.js +10 -0
  51. package/dist/formatters/builds/Formatter.js.map +1 -0
  52. package/dist/formatters/builds/JsonFormatter.js +44 -0
  53. package/dist/formatters/builds/JsonFormatter.js.map +1 -0
  54. package/dist/formatters/builds/PlainTextFormatter.js +113 -0
  55. package/dist/formatters/builds/PlainTextFormatter.js.map +1 -0
  56. package/dist/formatters/builds/index.js +26 -0
  57. package/dist/formatters/builds/index.js.map +1 -0
  58. package/dist/formatters/errors/AlfredFormatter.js +110 -0
  59. package/dist/formatters/errors/AlfredFormatter.js.map +1 -0
  60. package/dist/formatters/errors/Formatter.js +98 -0
  61. package/dist/formatters/errors/Formatter.js.map +1 -0
  62. package/dist/formatters/errors/JsonFormatter.js +63 -0
  63. package/dist/formatters/errors/JsonFormatter.js.map +1 -0
  64. package/dist/formatters/errors/PlainTextFormatter.js +52 -0
  65. package/dist/formatters/errors/PlainTextFormatter.js.map +1 -0
  66. package/dist/formatters/errors/index.js +26 -0
  67. package/dist/formatters/errors/index.js.map +1 -0
  68. package/dist/formatters/index.js +9 -0
  69. package/dist/formatters/index.js.map +1 -0
  70. package/dist/formatters/organizations/Formatter.js +10 -0
  71. package/dist/formatters/organizations/Formatter.js.map +1 -0
  72. package/dist/formatters/organizations/JsonFormatter.js +16 -0
  73. package/dist/formatters/organizations/JsonFormatter.js.map +1 -0
  74. package/dist/formatters/organizations/PlainTextFormatter.js +15 -0
  75. package/dist/formatters/organizations/PlainTextFormatter.js.map +1 -0
  76. package/dist/formatters/organizations/index.js +21 -0
  77. package/dist/formatters/organizations/index.js.map +1 -0
  78. package/dist/formatters/pipelines/AlfredFormatter.js +42 -0
  79. package/dist/formatters/pipelines/AlfredFormatter.js.map +1 -0
  80. package/dist/formatters/pipelines/Formatter.js +10 -0
  81. package/dist/formatters/pipelines/Formatter.js.map +1 -0
  82. package/dist/formatters/pipelines/JsonFormatter.js +13 -0
  83. package/dist/formatters/pipelines/JsonFormatter.js.map +1 -0
  84. package/dist/formatters/pipelines/PlainTextFormatter.js +47 -0
  85. package/dist/formatters/pipelines/PlainTextFormatter.js.map +1 -0
  86. package/dist/formatters/pipelines/index.js +28 -0
  87. package/dist/formatters/pipelines/index.js.map +1 -0
  88. package/dist/formatters/token/AlfredFormatter.js +191 -0
  89. package/dist/formatters/token/AlfredFormatter.js.map +1 -0
  90. package/dist/formatters/token/Formatter.js +13 -0
  91. package/dist/formatters/token/Formatter.js.map +1 -0
  92. package/dist/formatters/token/JsonFormatter.js +211 -0
  93. package/dist/formatters/token/JsonFormatter.js.map +1 -0
  94. package/dist/formatters/token/PlainTextFormatter.js +184 -0
  95. package/dist/formatters/token/PlainTextFormatter.js.map +1 -0
  96. package/dist/formatters/token/index.js +26 -0
  97. package/dist/formatters/token/index.js.map +1 -0
  98. package/dist/formatters/viewer/Formatter.js +10 -0
  99. package/dist/formatters/viewer/Formatter.js.map +1 -0
  100. package/dist/formatters/viewer/JsonFormatter.js +20 -0
  101. package/dist/formatters/viewer/JsonFormatter.js.map +1 -0
  102. package/dist/formatters/viewer/PlainTextFormatter.js +20 -0
  103. package/dist/formatters/viewer/PlainTextFormatter.js.map +1 -0
  104. package/dist/formatters/viewer/index.js +21 -0
  105. package/dist/formatters/viewer/index.js.map +1 -0
  106. package/dist/graphql/generated/fragment-masking.js +17 -0
  107. package/dist/graphql/generated/fragment-masking.js.map +1 -0
  108. package/dist/graphql/generated/gql.js +13 -0
  109. package/dist/graphql/generated/gql.js.map +1 -0
  110. package/dist/graphql/generated/graphql.js +852 -0
  111. package/dist/graphql/generated/graphql.js.map +1 -0
  112. package/dist/graphql/generated/index.js +3 -0
  113. package/dist/graphql/generated/index.js.map +1 -0
  114. package/dist/graphql/generated/sdk.js +872 -0
  115. package/dist/graphql/generated/sdk.js.map +1 -0
  116. package/dist/graphql/queries.js +138 -0
  117. package/dist/graphql/queries.js.map +1 -0
  118. package/dist/index.js +271 -0
  119. package/dist/index.js.map +1 -0
  120. package/dist/services/BuildkiteClient.js +520 -0
  121. package/dist/services/BuildkiteClient.js.map +1 -0
  122. package/dist/services/BuildkiteRestClient.js +244 -0
  123. package/dist/services/BuildkiteRestClient.js.map +1 -0
  124. package/dist/services/CacheManager.js +221 -0
  125. package/dist/services/CacheManager.js.map +1 -0
  126. package/dist/services/CredentialManager.js +158 -0
  127. package/dist/services/CredentialManager.js.map +1 -0
  128. package/dist/services/EnhancedBuildkiteClient.js +297 -0
  129. package/dist/services/EnhancedBuildkiteClient.js.map +1 -0
  130. package/dist/services/logger.js +107 -0
  131. package/dist/services/logger.js.map +1 -0
  132. package/dist/types/buildkite.js +5 -0
  133. package/dist/types/buildkite.js.map +1 -0
  134. package/dist/types/credentials.js +2 -0
  135. package/dist/types/credentials.js.map +1 -0
  136. package/dist/types/index.js +3 -0
  137. package/dist/types/index.js.map +1 -0
  138. package/dist/utils/cli-error-handler.js +172 -0
  139. package/dist/utils/cli-error-handler.js.map +1 -0
  140. package/dist/utils/errorUtils.js +59 -0
  141. package/dist/utils/errorUtils.js.map +1 -0
  142. package/dist/utils/parseBuildRef.js +31 -0
  143. package/dist/utils/parseBuildRef.js.map +1 -0
  144. package/dist/utils/textFormatter.js +53 -0
  145. package/dist/utils/textFormatter.js.map +1 -0
  146. package/dist/utils/xdgPaths.js +95 -0
  147. package/dist/utils/xdgPaths.js.map +1 -0
  148. package/env.example +66 -0
  149. package/icons/README.md +68 -0
  150. package/icons/blocked.png +0 -0
  151. package/icons/buildkite.png +0 -0
  152. package/icons/failed.png +0 -0
  153. package/icons/failing.png +0 -0
  154. package/icons/passed.png +0 -0
  155. package/icons/running.png +0 -0
  156. package/icons/scheduled.png +0 -0
  157. package/icons/skipped.png +0 -0
  158. package/icons/unknown.png +0 -0
  159. package/info.plist +734 -0
  160. package/package.json +87 -0
@@ -0,0 +1,137 @@
1
+ import { BaseCommand } from './BaseCommand.js';
2
+ import { getBuildFormatter } from '../formatters/index.js';
3
+ import Fuse from 'fuse.js';
4
+ import { logger } from '../services/logger.js';
5
+ export class ListBuilds extends BaseCommand {
6
+ constructor(options) {
7
+ super(options);
8
+ }
9
+ async execute(options) {
10
+ await this.ensureInitialized();
11
+ const executeStartTime = process.hrtime.bigint();
12
+ if (options.debug) {
13
+ logger.debug('Starting ViewerBuildsCommandHandler execution');
14
+ }
15
+ try {
16
+ // First, get the current user's information using GraphQL
17
+ const viewerData = await this.client.getViewer();
18
+ if (!viewerData?.viewer?.user?.uuid) {
19
+ logger.error('Failed to get current user UUID information');
20
+ return 1;
21
+ }
22
+ const userId = viewerData.viewer.user.uuid;
23
+ const userName = viewerData.viewer.user.name || 'Current user';
24
+ const userEmail = viewerData.viewer.user.email;
25
+ // Use the REST API to get builds by the current user
26
+ const perPage = options.count || '10';
27
+ const page = options.page || '1';
28
+ // If organization is not specified, we need to fetch organizations first
29
+ let orgs = [];
30
+ if (!options.org) {
31
+ // Try to fetch the user's organizations
32
+ try {
33
+ orgs = await this.client.getViewerOrganizationSlugs();
34
+ }
35
+ catch (error) {
36
+ logger.error(error, 'Failed to determine your organizations');
37
+ return 1;
38
+ }
39
+ }
40
+ else {
41
+ orgs = [options.org];
42
+ }
43
+ // Initialize results array
44
+ let allBuilds = [];
45
+ let accessErrors = [];
46
+ for (const org of orgs) {
47
+ try {
48
+ // First check if the user has access to this organization
49
+ const hasAccess = await this.restClient.hasOrganizationAccess(org);
50
+ if (!hasAccess) {
51
+ accessErrors.push(`You don't have access to organization ${org}`);
52
+ continue;
53
+ }
54
+ const builds = await this.restClient.getBuilds(org, {
55
+ creator: userId,
56
+ pipeline: options.pipeline,
57
+ branch: options.branch,
58
+ state: options.state,
59
+ per_page: perPage,
60
+ page: page
61
+ });
62
+ if (options.debug) {
63
+ logger.debug(`Received ${builds.length} builds from org ${org}`);
64
+ }
65
+ allBuilds = allBuilds.concat(builds);
66
+ }
67
+ catch (error) {
68
+ // Log unexpected errors but continue processing other orgs
69
+ logger.error(error, `Error fetching builds for org ${org}`);
70
+ }
71
+ }
72
+ // Prepare formatter options
73
+ const formatterOptions = {
74
+ debug: options.debug,
75
+ organizationsCount: orgs.length,
76
+ orgSpecified: !!options.org,
77
+ userName,
78
+ userEmail,
79
+ userId
80
+ };
81
+ // Handle the case where we have no builds due to access issues
82
+ if (allBuilds.length === 0 && accessErrors.length > 0) {
83
+ formatterOptions.hasError = true;
84
+ formatterOptions.errorType = 'access';
85
+ formatterOptions.accessErrors = accessErrors;
86
+ if (options.org) {
87
+ formatterOptions.errorMessage = `No builds found for ${userName} (${userEmail}) in organization ${options.org}. ${accessErrors[0]}`;
88
+ }
89
+ else {
90
+ formatterOptions.errorMessage = `No builds found for ${userName} (${userEmail}). Try specifying an organization with --org to narrow your search.`;
91
+ }
92
+ const format = options.format || 'plain';
93
+ const formatter = getBuildFormatter(format);
94
+ const output = formatter.formatBuilds(allBuilds, formatterOptions);
95
+ logger.console(output);
96
+ return 1;
97
+ }
98
+ // Limit to the requested number of builds
99
+ allBuilds = allBuilds.slice(0, parseInt(perPage, 10));
100
+ // Apply fuzzy filter if specified
101
+ if (options.filter) {
102
+ if (options.debug) {
103
+ logger.debug(`Applying fuzzy filter '${options.filter}' to ${allBuilds.length} builds`);
104
+ }
105
+ // Configure Fuse for fuzzy searching
106
+ const fuse = new Fuse(allBuilds, {
107
+ keys: ['pipeline.name', 'branch', 'message', 'creator.name', 'state'],
108
+ threshold: 0.4,
109
+ includeScore: true,
110
+ shouldSort: true
111
+ });
112
+ // Perform the fuzzy search
113
+ const searchResults = fuse.search(options.filter);
114
+ allBuilds = searchResults.map(result => result.item);
115
+ if (options.debug) {
116
+ logger.debug(`Filtered to ${allBuilds.length} builds matching '${options.filter}'`);
117
+ }
118
+ }
119
+ const format = options.format || 'plain';
120
+ const formatter = getBuildFormatter(format);
121
+ const output = formatter.formatBuilds(allBuilds, formatterOptions);
122
+ logger.console(output);
123
+ if (options.debug) {
124
+ const executeDuration = Number(process.hrtime.bigint() - executeStartTime) / 1000000;
125
+ logger.debug(`ViewerBuildsCommandHandler execution completed in ${executeDuration.toFixed(2)}ms`);
126
+ }
127
+ return 0; // Success
128
+ }
129
+ catch (error) {
130
+ // Only unexpected errors should reach here
131
+ // Let the base command handle the error display
132
+ this.handleError(error, options.debug);
133
+ return 1; // Error
134
+ }
135
+ }
136
+ }
137
+ //# sourceMappingURL=ListBuilds.js.map
@@ -0,0 +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}"]}
@@ -0,0 +1,27 @@
1
+ import { BaseCommand } from './BaseCommand.js';
2
+ import { logger } from '../services/logger.js';
3
+ import { FormatterType } from '../formatters/index.js';
4
+ export class ListOrganizations extends BaseCommand {
5
+ constructor(options) {
6
+ super(options);
7
+ }
8
+ async execute(options = {}) {
9
+ try {
10
+ const organizations = await this.client.getOrganizations();
11
+ if (options.debug) {
12
+ logger.debug(`Fetched ${organizations.length} organizations`);
13
+ }
14
+ // Get the appropriate formatter
15
+ const formatter = this.getFormatter(FormatterType.ORGANIZATION, options);
16
+ // Format and output the organizations
17
+ const output = formatter.formatOrganizations(organizations, { debug: options.debug });
18
+ logger.console(output);
19
+ return 0; // Success
20
+ }
21
+ catch (error) {
22
+ this.handleError(error, options.debug);
23
+ return 1; // Error
24
+ }
25
+ }
26
+ }
27
+ //# sourceMappingURL=ListOrganizations.js.map
@@ -0,0 +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} "]}
@@ -0,0 +1,114 @@
1
+ import { BaseCommand } from './BaseCommand.js';
2
+ import { getPipelineFormatter } from '../formatters/index.js';
3
+ import Fuse from 'fuse.js';
4
+ import { logger } from '../services/logger.js';
5
+ export class ListPipelines extends BaseCommand {
6
+ BATCH_SIZE = 500;
7
+ constructor(options) {
8
+ super(options);
9
+ }
10
+ async execute(options) {
11
+ await this.ensureInitialized();
12
+ try {
13
+ // Need to get organization info if not provided
14
+ const org = options.org;
15
+ if (!org) {
16
+ try {
17
+ const orgs = await this.client.getViewerOrganizationSlugs();
18
+ await this.listPipelines(orgs, options);
19
+ }
20
+ catch (error) {
21
+ logger.error(error, 'Failed to determine your organizations');
22
+ throw new Error('Failed to determine your organizations', { cause: error });
23
+ }
24
+ }
25
+ else {
26
+ await this.listPipelines([org], options);
27
+ }
28
+ return 0; // Success
29
+ }
30
+ catch (error) {
31
+ this.handleError(error, options.debug);
32
+ return 1; // Error
33
+ }
34
+ }
35
+ async listPipelines(organizations, options) {
36
+ let allPipelines = [];
37
+ for (const org of organizations) {
38
+ try {
39
+ const batchSize = this.BATCH_SIZE;
40
+ let hasNextPage = true;
41
+ let cursor = null;
42
+ const limitResults = options.count !== undefined;
43
+ const resultLimit = limitResults ? parseInt(options.count, 10) : Infinity;
44
+ while (hasNextPage && allPipelines.length < resultLimit) {
45
+ if (options.debug) {
46
+ logger.debug(`Fetching batch of pipelines from org ${org}, cursor: ${cursor || 'initial'}`);
47
+ }
48
+ const data = await this.client.getPipelines(org, batchSize, cursor || undefined);
49
+ if (data?.organization?.pipelines?.edges) {
50
+ // Add org information to each pipeline for display
51
+ const pipelines = data.organization.pipelines.edges
52
+ .filter(edge => edge !== null && edge.node !== null)
53
+ .map(edge => {
54
+ const node = edge.node;
55
+ return {
56
+ uuid: node.uuid || '',
57
+ id: node.id || '',
58
+ name: node.name || '',
59
+ slug: node.slug || '',
60
+ description: node.description,
61
+ url: node.url || '',
62
+ repository: node.repository,
63
+ organization: org
64
+ };
65
+ });
66
+ allPipelines = allPipelines.concat(pipelines);
67
+ }
68
+ // Check if we need to fetch more pages
69
+ hasNextPage = data?.organization?.pipelines?.pageInfo?.hasNextPage || false;
70
+ cursor = data?.organization?.pipelines?.pageInfo?.endCursor || null;
71
+ if (options.debug) {
72
+ logger.debug(`Fetched batch of ${data?.organization?.pipelines?.edges?.length || 0} pipelines from org ${org}`);
73
+ if (hasNextPage) {
74
+ logger.debug(`More pages available, cursor: ${cursor}`);
75
+ }
76
+ }
77
+ // If we're limiting results, stop after getting enough
78
+ if (limitResults && allPipelines.length >= resultLimit) {
79
+ break;
80
+ }
81
+ }
82
+ }
83
+ catch (error) {
84
+ throw new Error(`Error fetching pipelines for organization ${org}`, { cause: error });
85
+ }
86
+ }
87
+ // Apply limit if specified
88
+ if (options.count) {
89
+ const limit = parseInt(options.count, 10);
90
+ allPipelines = allPipelines.slice(0, limit);
91
+ }
92
+ if (options.filter && allPipelines.length > 0) {
93
+ if (options.debug) {
94
+ logger.debug(`Applying fuzzy filter '${options.filter}' to ${allPipelines.length} pipelines`);
95
+ }
96
+ const fuse = new Fuse(allPipelines, {
97
+ keys: ['name', 'slug', 'description'],
98
+ threshold: 0.4,
99
+ includeScore: true,
100
+ shouldSort: true
101
+ });
102
+ const searchResults = fuse.search(options.filter);
103
+ allPipelines = searchResults.map(result => result.item);
104
+ if (options.debug) {
105
+ logger.debug(`Filtered to ${allPipelines.length} pipelines matching '${options.filter}'`);
106
+ }
107
+ }
108
+ const format = options.format || 'plain';
109
+ const formatter = getPipelineFormatter(format);
110
+ const output = formatter.formatPipelines(allPipelines, organizations);
111
+ logger.console(output);
112
+ }
113
+ }
114
+ //# sourceMappingURL=ListPipelines.js.map
@@ -0,0 +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} "]}
@@ -0,0 +1,180 @@
1
+ import { BaseCommand } from './BaseCommand.js';
2
+ import { logger } from '../services/logger.js';
3
+ import prompts from 'prompts';
4
+ import { FormatterFactory, FormatterType } from '../formatters/FormatterFactory.js';
5
+ export class ManageToken extends BaseCommand {
6
+ formatter;
7
+ constructor(options) {
8
+ super(options);
9
+ this.formatter = FormatterFactory.getFormatter(FormatterType.TOKEN, options?.format);
10
+ }
11
+ static get requiresToken() {
12
+ return false;
13
+ }
14
+ async execute(options) {
15
+ try {
16
+ // Handle option priorities: if multiple options are provided,
17
+ // we'll process them in this priority: store > reset > check
18
+ if (options.store) {
19
+ const { success, errors } = await this.storeToken();
20
+ if (success) {
21
+ return 0;
22
+ }
23
+ else {
24
+ const formattedErrors = this.formatter.formatAuthErrors('storing', errors);
25
+ logger.console(formattedErrors);
26
+ return 1;
27
+ }
28
+ }
29
+ else if (options.reset) {
30
+ await this.resetToken();
31
+ }
32
+ else if (options.check) {
33
+ const { errors } = await this.checkToken();
34
+ if (errors.length > 0) {
35
+ const formattedErrors = this.formatter.formatAuthErrors('validating', errors);
36
+ logger.console(formattedErrors);
37
+ return 0;
38
+ }
39
+ }
40
+ else {
41
+ const { errors } = await this.checkOrStoreToken();
42
+ if (errors.length > 0) {
43
+ const formattedErrors = this.formatter.formatAuthErrors('checking or storing', errors);
44
+ logger.console(formattedErrors);
45
+ return 0;
46
+ }
47
+ }
48
+ return 0; // Success
49
+ }
50
+ catch (error) {
51
+ const formattedError = this.formatter.formatError('executing', error);
52
+ logger.console(formattedError);
53
+ return 1; // Error
54
+ }
55
+ }
56
+ async storeToken() {
57
+ try {
58
+ let tokenToStore;
59
+ // If token is provided in options, use it
60
+ if (this.options.token) {
61
+ tokenToStore = this.options.token;
62
+ }
63
+ else {
64
+ // Otherwise prompt the user
65
+ const response = await prompts({
66
+ type: 'password',
67
+ name: 'token',
68
+ message: 'Enter your Buildkite API token:',
69
+ validate: value => value.length > 0 ? true : 'Please enter a valid token'
70
+ });
71
+ // Check if user cancelled the prompt (Ctrl+C)
72
+ if (!response.token) {
73
+ return { success: false, errors: [new Error('Token storage cancelled')] };
74
+ }
75
+ tokenToStore = response.token;
76
+ }
77
+ // Ensure we have a valid token before proceeding
78
+ if (!tokenToStore) {
79
+ return { success: false, errors: [new Error('No token provided')] };
80
+ }
81
+ // Validate the token using the CredentialManager
82
+ const validationResult = await BaseCommand.credentialManager.validateToken(tokenToStore);
83
+ if (!validationResult.canListOrganizations) {
84
+ throw new Error('Token is invalid or does not have access to list organizations');
85
+ }
86
+ if (!validationResult.valid) {
87
+ const invalidOrgs = Object.entries(validationResult.organizations)
88
+ .filter(([_, status]) => !status.graphql || !status.builds || !status.organizations)
89
+ .map(([org, status]) => {
90
+ const invalidApis = [];
91
+ if (!status.graphql)
92
+ invalidApis.push('GraphQL');
93
+ if (!status.builds)
94
+ invalidApis.push('Builds');
95
+ if (!status.organizations)
96
+ invalidApis.push('Organizations');
97
+ return `${org} (${invalidApis.join(', ')})`;
98
+ });
99
+ throw new Error(`Token has limited access in some organizations: ${invalidOrgs.join(', ')}`);
100
+ }
101
+ // Store the token if it's valid
102
+ const success = await BaseCommand.credentialManager.saveToken(tokenToStore);
103
+ return { success, errors: [] };
104
+ }
105
+ catch (error) {
106
+ return { success: false, errors: [error] };
107
+ }
108
+ }
109
+ async resetToken() {
110
+ try {
111
+ const hadToken = await BaseCommand.credentialManager.hasToken();
112
+ let success = false;
113
+ if (hadToken) {
114
+ success = await BaseCommand.credentialManager.deleteToken();
115
+ }
116
+ const formattedResult = this.formatter.formatTokenResetResult(success, hadToken);
117
+ logger.console(formattedResult);
118
+ }
119
+ catch (error) {
120
+ const formattedError = this.formatter.formatError('resetting', error);
121
+ logger.console(formattedError);
122
+ }
123
+ }
124
+ async checkOrStoreToken() {
125
+ const { status, errors } = await this.checkToken();
126
+ if (!status.hasToken || !status.isValid) {
127
+ const { success, errors: storeErrors } = await this.storeToken();
128
+ if (success) {
129
+ return { stored: true, errors: [] };
130
+ }
131
+ else {
132
+ return { stored: false, errors: storeErrors };
133
+ }
134
+ }
135
+ return { stored: false, errors };
136
+ }
137
+ async checkToken() {
138
+ const hasToken = await BaseCommand.credentialManager.hasToken();
139
+ let isValid = false;
140
+ let validation = {
141
+ valid: false,
142
+ canListOrganizations: false,
143
+ organizations: {}
144
+ };
145
+ const errors = [];
146
+ if (hasToken) {
147
+ // Get the token for validation
148
+ const token = await BaseCommand.credentialManager.getToken();
149
+ if (!token) {
150
+ const tokenStatus = {
151
+ hasToken: false,
152
+ isValid: false,
153
+ validation: {
154
+ valid: false,
155
+ canListOrganizations: false,
156
+ organizations: {}
157
+ }
158
+ };
159
+ return { status: tokenStatus, errors };
160
+ }
161
+ // Validate the token using the CredentialManager
162
+ try {
163
+ validation = await BaseCommand.credentialManager.validateToken(token);
164
+ isValid = validation.valid && validation.canListOrganizations;
165
+ }
166
+ catch (error) {
167
+ errors.push(error);
168
+ }
169
+ }
170
+ const tokenStatus = {
171
+ hasToken,
172
+ isValid,
173
+ validation
174
+ };
175
+ const formattedResult = this.formatter.formatTokenStatus(tokenStatus);
176
+ logger.console(formattedResult);
177
+ return { status: tokenStatus, errors };
178
+ }
179
+ }
180
+ //# sourceMappingURL=ManageToken.js.map
@@ -0,0 +1 @@
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';\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} "]}
@@ -0,0 +1,53 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { BaseCommandHandler } from './BaseCommandHandler.js';
11
+ import { GET_ORGANIZATIONS } from '../graphql/queries.js';
12
+ export class OrganizationCommandHandler extends BaseCommandHandler {
13
+ constructor(token, options) {
14
+ super(token, options);
15
+ }
16
+ listOrganizations(options) {
17
+ return __awaiter(this, void 0, void 0, function* () {
18
+ var _a, _b;
19
+ try {
20
+ // Ensure initialization is complete
21
+ yield this.ensureInitialized();
22
+ const data = yield this.client.query(GET_ORGANIZATIONS);
23
+ // Debug output if debug option is enabled
24
+ if (options.debug) {
25
+ console.debug('API Response:', JSON.stringify(data, null, 2));
26
+ }
27
+ console.log('Your organizations:');
28
+ // Safely check if data and required properties exist
29
+ if (((_b = (_a = data === null || data === void 0 ? void 0 : data.viewer) === null || _a === void 0 ? void 0 : _a.organizations) === null || _b === void 0 ? void 0 : _b.edges) && Array.isArray(data.viewer.organizations.edges)) {
30
+ if (data.viewer.organizations.edges.length === 0) {
31
+ console.log('No organizations found.');
32
+ return;
33
+ }
34
+ data.viewer.organizations.edges.forEach((edge) => {
35
+ console.log(`- ${edge.node.name} (${edge.node.slug})`);
36
+ });
37
+ }
38
+ else {
39
+ console.log('No organizations data returned from API.');
40
+ if (options.debug) {
41
+ console.debug('Received data structure:', Object.keys(data || {}).join(', '));
42
+ }
43
+ }
44
+ }
45
+ catch (error) {
46
+ console.error('Error fetching organizations:');
47
+ this.handleError(error, options.debug);
48
+ process.exit(1);
49
+ }
50
+ });
51
+ }
52
+ }
53
+ //# sourceMappingURL=OrganizationCommandHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrganizationCommandHandler.js","sourceRoot":"/","sources":["commands/OrganizationCommandHandler.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,kBAAkB,EAAsB,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAM1D,MAAM,OAAO,0BAA2B,SAAQ,kBAAkB;IAChE,YAAY,KAAa,EAAE,OAAsC;QAC/D,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACxB,CAAC;IAEK,iBAAiB,CAAC,OAA4B;;;YAClD,IAAI,CAAC;gBACH,oCAAoC;gBACpC,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAE/B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAA6B,iBAAiB,CAAC,CAAC;gBAEpF,0CAA0C;gBAC1C,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;oBAClB,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBAChE,CAAC;gBAED,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;gBAEnC,qDAAqD;gBACrD,IAAI,CAAA,MAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,MAAM,0CAAE,aAAa,0CAAE,KAAK,KAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzF,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBACjD,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;wBACvC,OAAO;oBACT,CAAC;oBAED,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAA+B,EAAE,EAAE;wBAC1E,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;oBACzD,CAAC,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;oBACxD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;wBAClB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;oBAChF,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;gBAC/C,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;gBACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;KAAA;CACF","sourcesContent":["import { BaseCommandHandler, BaseCommandOptions } from './BaseCommandHandler.js';\nimport { GET_ORGANIZATIONS } from '../graphql/queries.js';\nimport { OrganizationsQueryResponse, Organization, GraphQLEdge } from '../types/index.js';\n\nexport interface OrganizationOptions extends BaseCommandOptions {\n}\n\nexport class OrganizationCommandHandler extends BaseCommandHandler {\n constructor(token: string, options?: Partial<OrganizationOptions>) {\n super(token, options);\n }\n \n async listOrganizations(options: OrganizationOptions): Promise<void> {\n try {\n // Ensure initialization is complete\n await this.ensureInitialized();\n \n const data = await this.client.query<OrganizationsQueryResponse>(GET_ORGANIZATIONS);\n \n // Debug output if debug option is enabled\n if (options.debug) {\n console.debug('API Response:', JSON.stringify(data, null, 2));\n }\n \n console.log('Your organizations:');\n \n // Safely check if data and required properties exist\n if (data?.viewer?.organizations?.edges && Array.isArray(data.viewer.organizations.edges)) {\n if (data.viewer.organizations.edges.length === 0) {\n console.log('No organizations found.');\n return;\n }\n \n data.viewer.organizations.edges.forEach((edge: GraphQLEdge<Organization>) => {\n console.log(`- ${edge.node.name} (${edge.node.slug})`);\n });\n } else {\n console.log('No organizations data returned from API.');\n if (options.debug) {\n console.debug('Received data structure:', Object.keys(data || {}).join(', '));\n }\n }\n } catch (error: any) {\n console.error('Error fetching organizations:');\n this.handleError(error, options.debug);\n process.exit(1);\n }\n }\n} "]}