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.
- package/README.md +145 -0
- package/WORKFLOW_README.md +65 -0
- package/bin/alfred-entrypoint +54 -0
- package/dist/commands/BaseCommand.js +159 -0
- package/dist/commands/BaseCommand.js.map +1 -0
- package/dist/commands/BaseCommandHandler.js +80 -0
- package/dist/commands/BaseCommandHandler.js.map +1 -0
- package/dist/commands/BuildCommandHandler.js +28 -0
- package/dist/commands/BuildCommandHandler.js.map +1 -0
- package/dist/commands/HelloCommandHandler.js +6 -0
- package/dist/commands/HelloCommandHandler.js.map +1 -0
- package/dist/commands/ListAnnotations.js +60 -0
- package/dist/commands/ListAnnotations.js.map +1 -0
- package/dist/commands/ListBuilds.js +137 -0
- package/dist/commands/ListBuilds.js.map +1 -0
- package/dist/commands/ListOrganizations.js +27 -0
- package/dist/commands/ListOrganizations.js.map +1 -0
- package/dist/commands/ListPipelines.js +114 -0
- package/dist/commands/ListPipelines.js.map +1 -0
- package/dist/commands/ManageToken.js +180 -0
- package/dist/commands/ManageToken.js.map +1 -0
- package/dist/commands/OrganizationCommandHandler.js +53 -0
- package/dist/commands/OrganizationCommandHandler.js.map +1 -0
- package/dist/commands/PipelineCommandHandler.js +142 -0
- package/dist/commands/PipelineCommandHandler.js.map +1 -0
- package/dist/commands/ShowViewer.js +26 -0
- package/dist/commands/ShowViewer.js.map +1 -0
- package/dist/commands/UserBuildsCommandHandler.js +61 -0
- package/dist/commands/UserBuildsCommandHandler.js.map +1 -0
- package/dist/commands/ViewerBuildsCommandHandler.js +176 -0
- package/dist/commands/ViewerBuildsCommandHandler.js.map +1 -0
- package/dist/commands/ViewerCommandHandler.js +46 -0
- package/dist/commands/ViewerCommandHandler.js.map +1 -0
- package/dist/commands/index.js +8 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/formatters/BaseFormatter.js +14 -0
- package/dist/formatters/BaseFormatter.js.map +1 -0
- package/dist/formatters/FormatterFactory.js +48 -0
- package/dist/formatters/FormatterFactory.js.map +1 -0
- package/dist/formatters/annotations/Formatter.js +10 -0
- package/dist/formatters/annotations/Formatter.js.map +1 -0
- package/dist/formatters/annotations/JsonFormatter.js +20 -0
- package/dist/formatters/annotations/JsonFormatter.js.map +1 -0
- package/dist/formatters/annotations/PlainTextFormatter.js +35 -0
- package/dist/formatters/annotations/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/annotations/index.js +23 -0
- package/dist/formatters/annotations/index.js.map +1 -0
- package/dist/formatters/builds/AlfredFormatter.js +135 -0
- package/dist/formatters/builds/AlfredFormatter.js.map +1 -0
- package/dist/formatters/builds/Formatter.js +10 -0
- package/dist/formatters/builds/Formatter.js.map +1 -0
- package/dist/formatters/builds/JsonFormatter.js +44 -0
- package/dist/formatters/builds/JsonFormatter.js.map +1 -0
- package/dist/formatters/builds/PlainTextFormatter.js +113 -0
- package/dist/formatters/builds/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/builds/index.js +26 -0
- package/dist/formatters/builds/index.js.map +1 -0
- package/dist/formatters/errors/AlfredFormatter.js +110 -0
- package/dist/formatters/errors/AlfredFormatter.js.map +1 -0
- package/dist/formatters/errors/Formatter.js +98 -0
- package/dist/formatters/errors/Formatter.js.map +1 -0
- package/dist/formatters/errors/JsonFormatter.js +63 -0
- package/dist/formatters/errors/JsonFormatter.js.map +1 -0
- package/dist/formatters/errors/PlainTextFormatter.js +52 -0
- package/dist/formatters/errors/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/errors/index.js +26 -0
- package/dist/formatters/errors/index.js.map +1 -0
- package/dist/formatters/index.js +9 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/formatters/organizations/Formatter.js +10 -0
- package/dist/formatters/organizations/Formatter.js.map +1 -0
- package/dist/formatters/organizations/JsonFormatter.js +16 -0
- package/dist/formatters/organizations/JsonFormatter.js.map +1 -0
- package/dist/formatters/organizations/PlainTextFormatter.js +15 -0
- package/dist/formatters/organizations/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/organizations/index.js +21 -0
- package/dist/formatters/organizations/index.js.map +1 -0
- package/dist/formatters/pipelines/AlfredFormatter.js +42 -0
- package/dist/formatters/pipelines/AlfredFormatter.js.map +1 -0
- package/dist/formatters/pipelines/Formatter.js +10 -0
- package/dist/formatters/pipelines/Formatter.js.map +1 -0
- package/dist/formatters/pipelines/JsonFormatter.js +13 -0
- package/dist/formatters/pipelines/JsonFormatter.js.map +1 -0
- package/dist/formatters/pipelines/PlainTextFormatter.js +47 -0
- package/dist/formatters/pipelines/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/pipelines/index.js +28 -0
- package/dist/formatters/pipelines/index.js.map +1 -0
- package/dist/formatters/token/AlfredFormatter.js +191 -0
- package/dist/formatters/token/AlfredFormatter.js.map +1 -0
- package/dist/formatters/token/Formatter.js +13 -0
- package/dist/formatters/token/Formatter.js.map +1 -0
- package/dist/formatters/token/JsonFormatter.js +211 -0
- package/dist/formatters/token/JsonFormatter.js.map +1 -0
- package/dist/formatters/token/PlainTextFormatter.js +184 -0
- package/dist/formatters/token/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/token/index.js +26 -0
- package/dist/formatters/token/index.js.map +1 -0
- package/dist/formatters/viewer/Formatter.js +10 -0
- package/dist/formatters/viewer/Formatter.js.map +1 -0
- package/dist/formatters/viewer/JsonFormatter.js +20 -0
- package/dist/formatters/viewer/JsonFormatter.js.map +1 -0
- package/dist/formatters/viewer/PlainTextFormatter.js +20 -0
- package/dist/formatters/viewer/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/viewer/index.js +21 -0
- package/dist/formatters/viewer/index.js.map +1 -0
- package/dist/graphql/generated/fragment-masking.js +17 -0
- package/dist/graphql/generated/fragment-masking.js.map +1 -0
- package/dist/graphql/generated/gql.js +13 -0
- package/dist/graphql/generated/gql.js.map +1 -0
- package/dist/graphql/generated/graphql.js +852 -0
- package/dist/graphql/generated/graphql.js.map +1 -0
- package/dist/graphql/generated/index.js +3 -0
- package/dist/graphql/generated/index.js.map +1 -0
- package/dist/graphql/generated/sdk.js +872 -0
- package/dist/graphql/generated/sdk.js.map +1 -0
- package/dist/graphql/queries.js +138 -0
- package/dist/graphql/queries.js.map +1 -0
- package/dist/index.js +271 -0
- package/dist/index.js.map +1 -0
- package/dist/services/BuildkiteClient.js +520 -0
- package/dist/services/BuildkiteClient.js.map +1 -0
- package/dist/services/BuildkiteRestClient.js +244 -0
- package/dist/services/BuildkiteRestClient.js.map +1 -0
- package/dist/services/CacheManager.js +221 -0
- package/dist/services/CacheManager.js.map +1 -0
- package/dist/services/CredentialManager.js +158 -0
- package/dist/services/CredentialManager.js.map +1 -0
- package/dist/services/EnhancedBuildkiteClient.js +297 -0
- package/dist/services/EnhancedBuildkiteClient.js.map +1 -0
- package/dist/services/logger.js +107 -0
- package/dist/services/logger.js.map +1 -0
- package/dist/types/buildkite.js +5 -0
- package/dist/types/buildkite.js.map +1 -0
- package/dist/types/credentials.js +2 -0
- package/dist/types/credentials.js.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/cli-error-handler.js +172 -0
- package/dist/utils/cli-error-handler.js.map +1 -0
- package/dist/utils/errorUtils.js +59 -0
- package/dist/utils/errorUtils.js.map +1 -0
- package/dist/utils/parseBuildRef.js +31 -0
- package/dist/utils/parseBuildRef.js.map +1 -0
- package/dist/utils/textFormatter.js +53 -0
- package/dist/utils/textFormatter.js.map +1 -0
- package/dist/utils/xdgPaths.js +95 -0
- package/dist/utils/xdgPaths.js.map +1 -0
- package/env.example +66 -0
- package/icons/README.md +68 -0
- package/icons/blocked.png +0 -0
- package/icons/buildkite.png +0 -0
- package/icons/failed.png +0 -0
- package/icons/failing.png +0 -0
- package/icons/passed.png +0 -0
- package/icons/running.png +0 -0
- package/icons/scheduled.png +0 -0
- package/icons/skipped.png +0 -0
- package/icons/unknown.png +0 -0
- package/info.plist +734 -0
- package/package.json +87 -0
|
@@ -0,0 +1,142 @@
|
|
|
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_PIPELINES } from '../graphql/queries.js';
|
|
12
|
+
import { getPipelineFormatter } from '../formatters/index.js';
|
|
13
|
+
import Fuse from 'fuse.js';
|
|
14
|
+
export class PipelineCommandHandler extends BaseCommandHandler {
|
|
15
|
+
constructor(token, options) {
|
|
16
|
+
super(token, options);
|
|
17
|
+
}
|
|
18
|
+
listPipelines(options) {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
21
|
+
try {
|
|
22
|
+
// Ensure initialization is complete
|
|
23
|
+
yield this.ensureInitialized();
|
|
24
|
+
// If organization is not specified, we need to fetch organizations first
|
|
25
|
+
let orgs = [];
|
|
26
|
+
if (!options.org) {
|
|
27
|
+
// Try to fetch the user's organizations
|
|
28
|
+
try {
|
|
29
|
+
orgs = yield this.client.getViewerOrganizationSlugs();
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
console.error('Error fetching organizations:', error);
|
|
33
|
+
throw new Error('Failed to determine your organizations. Please specify an organization with --org');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
orgs = [options.org];
|
|
38
|
+
}
|
|
39
|
+
// Initialize results array
|
|
40
|
+
let allPipelines = [];
|
|
41
|
+
// Fetch pipelines for each organization
|
|
42
|
+
for (const org of orgs) {
|
|
43
|
+
try {
|
|
44
|
+
const batchSize = 500;
|
|
45
|
+
let hasNextPage = true;
|
|
46
|
+
let cursor = null;
|
|
47
|
+
const limitResults = options.count !== undefined;
|
|
48
|
+
const resultLimit = limitResults ? parseInt(options.count, 10) : Infinity;
|
|
49
|
+
while (hasNextPage && allPipelines.length < resultLimit) {
|
|
50
|
+
const variables = {
|
|
51
|
+
organizationSlug: org,
|
|
52
|
+
first: batchSize
|
|
53
|
+
};
|
|
54
|
+
if (cursor) {
|
|
55
|
+
variables.after = cursor;
|
|
56
|
+
}
|
|
57
|
+
const data = yield this.client.query(GET_PIPELINES, variables);
|
|
58
|
+
if ((_b = (_a = data === null || data === void 0 ? void 0 : data.organization) === null || _a === void 0 ? void 0 : _a.pipelines) === null || _b === void 0 ? void 0 : _b.edges) {
|
|
59
|
+
// Add org information to each pipeline for display
|
|
60
|
+
const pipelines = data.organization.pipelines.edges.map((edge) => (Object.assign(Object.assign({}, edge.node), { organization: org })));
|
|
61
|
+
allPipelines = allPipelines.concat(pipelines);
|
|
62
|
+
}
|
|
63
|
+
// Check if we need to fetch more pages
|
|
64
|
+
hasNextPage = ((_e = (_d = (_c = data === null || data === void 0 ? void 0 : data.organization) === null || _c === void 0 ? void 0 : _c.pipelines) === null || _d === void 0 ? void 0 : _d.pageInfo) === null || _e === void 0 ? void 0 : _e.hasNextPage) || false;
|
|
65
|
+
cursor = ((_h = (_g = (_f = data === null || data === void 0 ? void 0 : data.organization) === null || _f === void 0 ? void 0 : _f.pipelines) === null || _g === void 0 ? void 0 : _g.pageInfo) === null || _h === void 0 ? void 0 : _h.endCursor) || null;
|
|
66
|
+
if (options.debug) {
|
|
67
|
+
console.log(`Debug: Fetched batch of ${((_l = (_k = (_j = data === null || data === void 0 ? void 0 : data.organization) === null || _j === void 0 ? void 0 : _j.pipelines) === null || _k === void 0 ? void 0 : _k.edges) === null || _l === void 0 ? void 0 : _l.length) || 0} pipelines from org ${org}`);
|
|
68
|
+
if (hasNextPage) {
|
|
69
|
+
console.log(`Debug: More pages available, cursor: ${cursor}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// If we're limiting results, stop after getting enough
|
|
73
|
+
if (limitResults && allPipelines.length >= resultLimit) {
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
if (options.debug) {
|
|
80
|
+
console.error(`Error fetching pipelines for org ${org}:`, error);
|
|
81
|
+
}
|
|
82
|
+
// Continue to the next organization
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Limit to the requested number of pipelines if specified
|
|
86
|
+
if (options.count !== undefined) {
|
|
87
|
+
allPipelines = allPipelines.slice(0, parseInt(options.count, 10));
|
|
88
|
+
}
|
|
89
|
+
// Filter pipelines by name if filter is specified
|
|
90
|
+
if (options.filter) {
|
|
91
|
+
if (options.debug) {
|
|
92
|
+
console.log(`Debug: Applying fuzzy filter '${options.filter}' to ${allPipelines.length} pipelines`);
|
|
93
|
+
}
|
|
94
|
+
// Configure Fuse for fuzzy searching
|
|
95
|
+
const fuse = new Fuse(allPipelines, {
|
|
96
|
+
keys: ['name', 'slug'],
|
|
97
|
+
threshold: 0.4, // Lower threshold = more strict matching
|
|
98
|
+
includeScore: true,
|
|
99
|
+
shouldSort: true
|
|
100
|
+
});
|
|
101
|
+
// Perform the fuzzy search
|
|
102
|
+
const searchResults = fuse.search(options.filter);
|
|
103
|
+
allPipelines = searchResults.map(result => result.item);
|
|
104
|
+
if (options.debug) {
|
|
105
|
+
console.log(`Debug: Filtered to ${allPipelines.length} pipelines matching '${options.filter}'`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
// Get the appropriate formatter
|
|
110
|
+
// Format precedence: command line option > constructor option > default
|
|
111
|
+
const format = options.format || this.options.format || 'plain';
|
|
112
|
+
if (options.debug) {
|
|
113
|
+
console.log(`Debug: Using ${format} formatter`);
|
|
114
|
+
}
|
|
115
|
+
const formatter = getPipelineFormatter(format);
|
|
116
|
+
// Format and output the results
|
|
117
|
+
const output = formatter.formatPipelines(allPipelines, orgs, { debug: options.debug });
|
|
118
|
+
console.log(output);
|
|
119
|
+
}
|
|
120
|
+
catch (formatterError) {
|
|
121
|
+
console.error('Error formatting output:', formatterError);
|
|
122
|
+
if (options.debug) {
|
|
123
|
+
console.error('Error details:', formatterError);
|
|
124
|
+
}
|
|
125
|
+
// Fallback to simple output if formatter fails
|
|
126
|
+
if (allPipelines.length === 0) {
|
|
127
|
+
console.log('No pipelines found.');
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
console.log(`Found ${allPipelines.length} pipelines.`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
console.error('Error fetching pipelines:');
|
|
136
|
+
this.handleError(error, options.debug);
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=PipelineCommandHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PipelineCommandHandler.js","sourceRoot":"/","sources":["commands/PipelineCommandHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseCommandHandler, BaseCommandOptions } from './BaseCommandHandler.js';\nimport { GET_PIPELINES } from '../graphql/queries.js';\nimport { getPipelineFormatter } from '../formatters/index.js';\nimport Fuse from 'fuse.js';\nimport { Pipeline, PipelineQueryResponse } from '../types/index.js';\n\nexport interface PipelineOptions extends BaseCommandOptions {\n org?: string;\n count?: string;\n}\n\nexport class PipelineCommandHandler extends BaseCommandHandler {\n constructor(token: string, options?: Partial<PipelineOptions>) {\n super(token, options);\n }\n\n async listPipelines(options: PipelineOptions): Promise<void> {\n try {\n // Ensure initialization is complete\n await this.ensureInitialized();\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 console.error('Error fetching organizations:', error);\n throw new Error('Failed to determine your organizations. Please specify an organization with --org');\n }\n } else {\n orgs = [options.org];\n }\n \n // Initialize results array\n let allPipelines: Pipeline[] = [];\n \n // Fetch pipelines for each organization\n for (const org of orgs) {\n try {\n const batchSize = 500;\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 const variables: { \n organizationSlug: string;\n first: number;\n after?: string;\n } = {\n organizationSlug: org,\n first: batchSize\n };\n \n if (cursor) {\n variables.after = cursor;\n }\n \n const data = await this.client.query<PipelineQueryResponse>(GET_PIPELINES, variables);\n \n if (data?.organization?.pipelines?.edges) {\n // Add org information to each pipeline for display\n const pipelines: Pipeline[] = data.organization.pipelines.edges.map((edge) => ({\n ...edge.node,\n organization: org\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 console.log(`Debug: Fetched batch of ${data?.organization?.pipelines?.edges?.length || 0} pipelines from org ${org}`);\n if (hasNextPage) {\n console.log(`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 if (options.debug) {\n console.error(`Error fetching pipelines for org ${org}:`, error);\n }\n // Continue to the next organization\n }\n }\n \n // Limit to the requested number of pipelines if specified\n if (options.count !== undefined) {\n allPipelines = allPipelines.slice(0, parseInt(options.count as string, 10));\n }\n \n // Filter pipelines by name if filter is specified\n if (options.filter) {\n if (options.debug) {\n console.log(`Debug: Applying fuzzy filter '${options.filter}' to ${allPipelines.length} pipelines`);\n }\n \n // Configure Fuse for fuzzy searching\n const fuse = new Fuse(allPipelines, {\n keys: ['name', 'slug'],\n threshold: 0.4, // Lower threshold = more strict matching\n includeScore: true,\n shouldSort: true\n });\n \n // Perform the fuzzy search\n const searchResults = fuse.search(options.filter);\n allPipelines = searchResults.map(result => result.item);\n \n if (options.debug) {\n console.log(`Debug: Filtered to ${allPipelines.length} pipelines matching '${options.filter}'`);\n }\n }\n \n try {\n // Get the appropriate formatter\n // Format precedence: command line option > constructor option > default\n const format = options.format || this.options.format || 'plain';\n if (options.debug) {\n console.log(`Debug: Using ${format} formatter`);\n }\n const formatter = getPipelineFormatter(format);\n \n // Format and output the results\n const output = formatter.formatPipelines(allPipelines, orgs, { debug: options.debug });\n console.log(output);\n } catch (formatterError) {\n console.error('Error formatting output:', formatterError);\n if (options.debug) {\n console.error('Error details:', formatterError);\n }\n // Fallback to simple output if formatter fails\n if (allPipelines.length === 0) {\n console.log('No pipelines found.');\n } else {\n console.log(`Found ${allPipelines.length} pipelines.`);\n }\n }\n } catch (error: any) {\n console.error('Error fetching pipelines:');\n this.handleError(error, options.debug);\n process.exit(1);\n }\n }\n} "]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BaseCommand } from './BaseCommand.js';
|
|
2
|
+
import { getViewerFormatter } from '../formatters/index.js';
|
|
3
|
+
import { logger } from '../services/logger.js';
|
|
4
|
+
export class ShowViewer extends BaseCommand {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
super(options);
|
|
7
|
+
}
|
|
8
|
+
async execute(options) {
|
|
9
|
+
await this.ensureInitialized();
|
|
10
|
+
try {
|
|
11
|
+
const data = await this.client.getViewer();
|
|
12
|
+
if (!data?.viewer) {
|
|
13
|
+
throw new Error('Invalid response format: missing viewer data');
|
|
14
|
+
}
|
|
15
|
+
const formatter = getViewerFormatter(options.format || 'plain');
|
|
16
|
+
const output = formatter.formatViewer(data, { debug: options.debug });
|
|
17
|
+
logger.console(output);
|
|
18
|
+
return 0; // Success
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
this.handleError(error, options.debug);
|
|
22
|
+
return 1; // Error
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=ShowViewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShowViewer.js","sourceRoot":"/","sources":["commands/ShowViewer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAsB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAK/C,MAAM,OAAO,UAAW,SAAQ,WAAW;IACzC,YAAY,OAAgC;QAC1C,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAsB;QAClC,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YAE3C,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;gBAClB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAClE,CAAC;YAED,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC;YAChE,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,IAA6B,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;YAE/F,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACvB,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 { getViewerFormatter } from '../formatters/index.js';\nimport { ViewerData } from '../types/index.js';\nimport { logger } from '../services/logger.js';\n\nexport interface ViewerOptions extends BaseCommandOptions {\n}\n\nexport class ShowViewer extends BaseCommand {\n constructor(options?: Partial<ViewerOptions>) {\n super(options);\n }\n \n async execute(options: ViewerOptions): Promise<number> {\n await this.ensureInitialized();\n \n try {\n const data = await this.client.getViewer();\n \n if (!data?.viewer) {\n throw new Error('Invalid response format: missing viewer data');\n }\n \n const formatter = getViewerFormatter(options.format || 'plain');\n const output = formatter.formatViewer(data as unknown as ViewerData, { debug: options.debug });\n \n logger.console(output);\n return 0; // Success\n } catch (error) {\n this.handleError(error, options.debug);\n return 1; // Error\n }\n }\n} "]}
|
|
@@ -0,0 +1,61 @@
|
|
|
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 { BuildkiteRestClient } from '../services/BuildkiteRestClient.js';
|
|
12
|
+
export class UserBuildsCommandHandler extends BaseCommandHandler {
|
|
13
|
+
constructor(token) {
|
|
14
|
+
super(token);
|
|
15
|
+
this.restClient = new BuildkiteRestClient(token);
|
|
16
|
+
}
|
|
17
|
+
execute(options) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
try {
|
|
20
|
+
// Parse options
|
|
21
|
+
const perPage = options.count || '10';
|
|
22
|
+
const page = options.page || '1';
|
|
23
|
+
// Call the REST API to get builds by user
|
|
24
|
+
const builds = yield this.restClient.getBuilds(options.org, {
|
|
25
|
+
creator: options.user,
|
|
26
|
+
pipeline: options.pipeline,
|
|
27
|
+
branch: options.branch,
|
|
28
|
+
state: options.state,
|
|
29
|
+
per_page: perPage,
|
|
30
|
+
page: page
|
|
31
|
+
});
|
|
32
|
+
if (builds.length === 0) {
|
|
33
|
+
console.log(`No builds found for user "${options.user}" in organization "${options.org}".`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
console.log(`Builds for user "${options.user}" in "${options.org}":"`);
|
|
37
|
+
console.log('==========================================');
|
|
38
|
+
builds.forEach((build) => {
|
|
39
|
+
console.log(`Pipeline: ${build.pipeline.slug} #${build.number}`);
|
|
40
|
+
console.log(`State: ${build.state}`);
|
|
41
|
+
console.log(`Branch: ${build.branch}`);
|
|
42
|
+
console.log(`Message: ${build.message || 'No message'}`);
|
|
43
|
+
console.log(`Created: ${new Date(build.created_at).toLocaleString()}`);
|
|
44
|
+
console.log(`URL: ${build.web_url}`);
|
|
45
|
+
console.log('------------------');
|
|
46
|
+
});
|
|
47
|
+
console.log(`Page ${page} with ${builds.length} results. Use --page and --count options to navigate.`);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error('Error fetching builds by user:');
|
|
51
|
+
this.handleError(error, options.debug);
|
|
52
|
+
// Show additional debug info
|
|
53
|
+
if (options.debug) {
|
|
54
|
+
console.error('UserBuildsCommandHandler Error Details:', error);
|
|
55
|
+
}
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=UserBuildsCommandHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserBuildsCommandHandler.js","sourceRoot":"/","sources":["commands/UserBuildsCommandHandler.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAczE,MAAM,OAAO,wBAAyB,SAAQ,kBAAkB;IAG9D,YAAY,KAAa;QACvB,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,UAAU,GAAG,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACnD,CAAC;IAEK,OAAO,CAAC,OAA0B;;YACtC,IAAI,CAAC;gBACH,gBAAgB;gBAChB,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;gBACtC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,CAAC;gBAEjC,0CAA0C;gBAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE;oBAC1D,OAAO,EAAE,OAAO,CAAC,IAAI;oBACrB,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,IAAI;iBACX,CAAC,CAAC;gBAEH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACxB,OAAO,CAAC,GAAG,CAAC,6BAA6B,OAAO,CAAC,IAAI,sBAAsB,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;oBAC5F,OAAO;gBACT,CAAC;gBAED,OAAO,CAAC,GAAG,CAAC,oBAAoB,OAAO,CAAC,IAAI,SAAS,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;gBACvE,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;gBAE1D,MAAM,CAAC,OAAO,CAAC,CAAC,KAAU,EAAE,EAAE;oBAC5B,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;oBACjE,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;oBACrC,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;oBACvC,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,OAAO,IAAI,YAAY,EAAE,CAAC,CAAC;oBACzD,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;oBACvE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;oBACrC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;gBACpC,CAAC,CAAC,CAAC;gBAEH,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS,MAAM,CAAC,MAAM,uDAAuD,CAAC,CAAC;YACzG,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;gBAChD,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;gBAEvC,6BAA6B;gBAC7B,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;oBAClB,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,KAAK,CAAC,CAAC;gBAClE,CAAC;gBAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;KAAA;CACF","sourcesContent":["import { BaseCommandHandler } from './BaseCommandHandler.js';\nimport { BuildkiteRestClient } from '../services/BuildkiteRestClient.js';\n\nexport interface UserBuildsOptions {\n token?: string;\n org: string;\n user: string;\n count?: string;\n page?: string;\n pipeline?: string;\n branch?: string;\n state?: string;\n debug?: boolean;\n}\n\nexport class UserBuildsCommandHandler extends BaseCommandHandler {\n private restClient: BuildkiteRestClient;\n\n constructor(token: string) {\n super(token);\n this.restClient = new BuildkiteRestClient(token);\n }\n\n async execute(options: UserBuildsOptions): Promise<void> {\n try {\n // Parse options\n const perPage = options.count || '10';\n const page = options.page || '1';\n \n // Call the REST API to get builds by user\n const builds = await this.restClient.getBuilds(options.org, {\n creator: options.user,\n pipeline: options.pipeline,\n branch: options.branch,\n state: options.state,\n per_page: perPage,\n page: page\n });\n \n if (builds.length === 0) {\n console.log(`No builds found for user \"${options.user}\" in organization \"${options.org}\".`);\n return;\n }\n \n console.log(`Builds for user \"${options.user}\" in \"${options.org}\":\"`);\n console.log('==========================================');\n \n builds.forEach((build: any) => {\n console.log(`Pipeline: ${build.pipeline.slug} #${build.number}`);\n console.log(`State: ${build.state}`);\n console.log(`Branch: ${build.branch}`);\n console.log(`Message: ${build.message || 'No message'}`);\n console.log(`Created: ${new Date(build.created_at).toLocaleString()}`);\n console.log(`URL: ${build.web_url}`);\n console.log('------------------');\n });\n \n console.log(`Page ${page} with ${builds.length} results. Use --page and --count options to navigate.`);\n } catch (error: any) {\n console.error('Error fetching builds by user:');\n this.handleError(error, options.debug);\n \n // Show additional debug info\n if (options.debug) {\n console.error('UserBuildsCommandHandler Error Details:', error);\n }\n \n process.exit(1);\n }\n }\n} "]}
|
|
@@ -0,0 +1,176 @@
|
|
|
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_VIEWER } from '../graphql/queries.js';
|
|
12
|
+
import { BuildkiteRestClient } from '../services/BuildkiteRestClient.js';
|
|
13
|
+
import { getBuildFormatter } from '../formatters/index.js';
|
|
14
|
+
import Fuse from 'fuse.js';
|
|
15
|
+
// Add a custom console.debug that respects the debug flag
|
|
16
|
+
const createDebugLogger = (isDebugEnabled) => {
|
|
17
|
+
return (...args) => {
|
|
18
|
+
if (isDebugEnabled) {
|
|
19
|
+
console.log('[DEBUG]', ...args);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export class ViewerBuildsCommandHandler extends BaseCommandHandler {
|
|
24
|
+
constructor(token, options) {
|
|
25
|
+
super(token, options);
|
|
26
|
+
// Configure REST client with the same caching options
|
|
27
|
+
const restClientOptions = {
|
|
28
|
+
debug: options === null || options === void 0 ? void 0 : options.debug,
|
|
29
|
+
caching: !(options === null || options === void 0 ? void 0 : options.noCache),
|
|
30
|
+
};
|
|
31
|
+
// If a specific cache TTL is provided, apply it to REST client
|
|
32
|
+
if (options === null || options === void 0 ? void 0 : options.cacheTTL) {
|
|
33
|
+
restClientOptions.cacheTTLs = {
|
|
34
|
+
default: options.cacheTTL,
|
|
35
|
+
builds: options.cacheTTL,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
this.restClient = new BuildkiteRestClient(token, restClientOptions);
|
|
39
|
+
}
|
|
40
|
+
execute(options) {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
var _a, _b;
|
|
43
|
+
// Declare originalDebug outside the try block so it's accessible in catch
|
|
44
|
+
const originalDebug = console.debug;
|
|
45
|
+
try {
|
|
46
|
+
// Override console.debug to respect the debug flag
|
|
47
|
+
console.debug = createDebugLogger(!!options.debug);
|
|
48
|
+
// Ensure initialization is complete
|
|
49
|
+
yield this.ensureInitialized();
|
|
50
|
+
const executeStartTime = process.hrtime.bigint();
|
|
51
|
+
if (options.debug) {
|
|
52
|
+
console.log('[DEBUG] Starting ViewerBuildsCommandHandler execution');
|
|
53
|
+
}
|
|
54
|
+
// First, get the current user's information using GraphQL
|
|
55
|
+
const viewerData = yield this.client.query(GET_VIEWER);
|
|
56
|
+
if (!((_b = (_a = viewerData === null || viewerData === void 0 ? void 0 : viewerData.viewer) === null || _a === void 0 ? void 0 : _a.user) === null || _b === void 0 ? void 0 : _b.uuid)) {
|
|
57
|
+
throw new Error('Failed to get current user UUID information');
|
|
58
|
+
}
|
|
59
|
+
const userId = viewerData.viewer.user.uuid;
|
|
60
|
+
const userName = viewerData.viewer.user.name || 'Current user';
|
|
61
|
+
const userEmail = viewerData.viewer.user.email;
|
|
62
|
+
// Use the REST API to get builds by the current user
|
|
63
|
+
const perPage = options.count || '10';
|
|
64
|
+
const page = options.page || '1';
|
|
65
|
+
// If organization is not specified, we need to fetch organizations first
|
|
66
|
+
let orgs = [];
|
|
67
|
+
if (!options.org) {
|
|
68
|
+
// Try to fetch the user's organizations
|
|
69
|
+
try {
|
|
70
|
+
orgs = yield this.client.getViewerOrganizationSlugs();
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.error('Error fetching organizations:', error);
|
|
74
|
+
throw new Error('Failed to determine your organizations. Please specify an organization with --org');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
orgs = [options.org];
|
|
79
|
+
}
|
|
80
|
+
// Initialize results array
|
|
81
|
+
let allBuilds = [];
|
|
82
|
+
for (const org of orgs) {
|
|
83
|
+
try {
|
|
84
|
+
const builds = yield this.restClient.getBuilds(org, {
|
|
85
|
+
creator: userId,
|
|
86
|
+
pipeline: options.pipeline,
|
|
87
|
+
branch: options.branch,
|
|
88
|
+
state: options.state,
|
|
89
|
+
per_page: perPage,
|
|
90
|
+
page: page
|
|
91
|
+
});
|
|
92
|
+
if (options.debug) {
|
|
93
|
+
console.log(`Debug: Received ${builds.length} builds from org ${org}`);
|
|
94
|
+
}
|
|
95
|
+
allBuilds = allBuilds.concat(builds);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
if (options.debug) {
|
|
99
|
+
console.error(`Error fetching builds for org ${org}:`, error);
|
|
100
|
+
}
|
|
101
|
+
// Continue to the next organization
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Limit to the requested number of builds
|
|
105
|
+
allBuilds = allBuilds.slice(0, parseInt(perPage, 10));
|
|
106
|
+
// Apply fuzzy filter if specified
|
|
107
|
+
if (options.filter) {
|
|
108
|
+
if (options.debug) {
|
|
109
|
+
console.log(`Debug: Applying fuzzy filter '${options.filter}' to ${allBuilds.length} builds`);
|
|
110
|
+
}
|
|
111
|
+
// Configure Fuse for fuzzy searching
|
|
112
|
+
const fuse = new Fuse(allBuilds, {
|
|
113
|
+
keys: ['pipeline.name', 'branch', 'message', 'creator.name', 'state'],
|
|
114
|
+
threshold: 0.4,
|
|
115
|
+
includeScore: true,
|
|
116
|
+
shouldSort: true
|
|
117
|
+
});
|
|
118
|
+
// Perform the fuzzy search
|
|
119
|
+
const searchResults = fuse.search(options.filter);
|
|
120
|
+
allBuilds = searchResults.map(result => result.item);
|
|
121
|
+
if (options.debug) {
|
|
122
|
+
console.log(`Debug: Filtered to ${allBuilds.length} builds matching '${options.filter}'`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (allBuilds.length === 0) {
|
|
126
|
+
// Determine the format type based on options
|
|
127
|
+
const format = options.format || 'plain';
|
|
128
|
+
if (format === 'alfred') {
|
|
129
|
+
// Return empty Alfred JSON format
|
|
130
|
+
console.log(JSON.stringify({ items: [] }));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
else if (format === 'json') {
|
|
134
|
+
console.log(JSON.stringify([]));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
console.log(`No builds found for ${userName} (${userEmail || userId}).`);
|
|
138
|
+
if (!options.org) {
|
|
139
|
+
console.log('Try specifying an organization with --org to narrow your search.');
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
// Get the appropriate formatter based on format option
|
|
144
|
+
const format = options.format || 'plain';
|
|
145
|
+
const formatter = getBuildFormatter(format);
|
|
146
|
+
const output = formatter.formatBuilds(allBuilds, { debug: options.debug });
|
|
147
|
+
// Print the output
|
|
148
|
+
console.log(output);
|
|
149
|
+
if (format === 'plain') {
|
|
150
|
+
console.log(`Showing ${allBuilds.length} builds. Use --count and --page options to see more.`);
|
|
151
|
+
if (!options.org && orgs.length > 1) {
|
|
152
|
+
console.log(`Searched across ${orgs.length} organizations. Use --org to filter to a specific organization.`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (options.debug) {
|
|
156
|
+
const executeDuration = Number(process.hrtime.bigint() - executeStartTime) / 1000000;
|
|
157
|
+
console.log(`[DEBUG] ViewerBuildsCommandHandler execution completed in ${executeDuration.toFixed(2)}ms`);
|
|
158
|
+
}
|
|
159
|
+
// Restore original console.debug
|
|
160
|
+
console.debug = originalDebug;
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
// Restore original console.debug in case of error
|
|
164
|
+
console.debug = originalDebug;
|
|
165
|
+
console.error('Error fetching builds:');
|
|
166
|
+
this.handleError(error, options.debug);
|
|
167
|
+
// Show additional debug info
|
|
168
|
+
if (options.debug) {
|
|
169
|
+
console.error('ViewerBuildsCommandHandler Error Details:', error);
|
|
170
|
+
}
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=ViewerBuildsCommandHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ViewerBuildsCommandHandler.js","sourceRoot":"/","sources":["commands/ViewerBuildsCommandHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseCommandHandler, BaseCommandOptions } from './BaseCommandHandler.js';\nimport { GET_VIEWER, GET_VIEWER_BUILDS } from '../graphql/queries.js';\nimport { BuildkiteRestClient, BuildkiteRestClientOptions } from '../services/BuildkiteRestClient.js';\nimport { BuildkiteClient } from '../services/BuildkiteClient.js';\nimport { getBuildFormatter } from '../formatters/index.js';\nimport Fuse from 'fuse.js';\nimport { Build, ViewerBuildsQueryResponse, ViewerData } from '../types/index.js';\n\n// Add a custom console.debug that respects the debug flag\nconst createDebugLogger = (isDebugEnabled: boolean) => {\n return (...args: any[]) => {\n if (isDebugEnabled) {\n console.log('[DEBUG]', ...args);\n }\n };\n};\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 ViewerBuildsCommandHandler extends BaseCommandHandler {\n private restClient: BuildkiteRestClient;\n\n constructor(token: string, options?: Partial<ViewerBuildsOptions>) {\n super(token, options);\n \n // Configure REST client with the same caching options\n const restClientOptions: BuildkiteRestClientOptions = {\n debug: options?.debug,\n caching: !options?.noCache,\n };\n \n // If a specific cache TTL is provided, apply it to REST client\n if (options?.cacheTTL) {\n restClientOptions.cacheTTLs = {\n default: options.cacheTTL,\n builds: options.cacheTTL,\n };\n }\n \n this.restClient = new BuildkiteRestClient(token, restClientOptions);\n }\n\n async execute(options: ViewerBuildsOptions): Promise<void> {\n // Declare originalDebug outside the try block so it's accessible in catch\n const originalDebug = console.debug;\n \n try {\n // Override console.debug to respect the debug flag\n console.debug = createDebugLogger(!!options.debug);\n \n // Ensure initialization is complete\n await this.ensureInitialized();\n \n const executeStartTime = process.hrtime.bigint();\n if (options.debug) {\n console.log('[DEBUG] Starting ViewerBuildsCommandHandler execution');\n }\n \n // First, get the current user's information using GraphQL\n const viewerData = await this.client.query<ViewerData>(GET_VIEWER);\n \n if (!viewerData?.viewer?.user?.uuid) {\n throw new Error('Failed to get current user UUID information');\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 console.error('Error fetching organizations:', error);\n throw new Error('Failed to determine your organizations. Please specify an organization with --org');\n }\n } else {\n orgs = [options.org];\n }\n \n // Initialize results array\n let allBuilds: Build[] = [];\n \n for (const org of orgs) {\n try {\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 console.log(`Debug: Received ${builds.length} builds from org ${org}`);\n }\n \n allBuilds = allBuilds.concat(builds);\n } catch (error) {\n if (options.debug) {\n console.error(`Error fetching builds for org ${org}:`, error);\n }\n // Continue to the next organization\n }\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 console.log(`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 console.log(`Debug: Filtered to ${allBuilds.length} builds matching '${options.filter}'`);\n }\n }\n \n if (allBuilds.length === 0) {\n // Determine the format type based on options\n const format = options.format || 'plain';\n \n if (format === 'alfred') {\n // Return empty Alfred JSON format\n console.log(JSON.stringify({ items: [] }));\n return;\n } else if (format === 'json') {\n console.log(JSON.stringify([]));\n return;\n }\n console.log(`No builds found for ${userName} (${userEmail || userId}).`);\n if (!options.org) {\n console.log('Try specifying an organization with --org to narrow your search.');\n }\n return;\n }\n \n // Get the appropriate formatter based on format option\n const format = options.format || 'plain';\n const formatter = getBuildFormatter(format);\n const output = formatter.formatBuilds(allBuilds, { debug: options.debug });\n \n // Print the output\n console.log(output);\n \n if (format === 'plain') {\n console.log(`Showing ${allBuilds.length} builds. Use --count and --page options to see more.`);\n \n if (!options.org && orgs.length > 1) {\n console.log(`Searched across ${orgs.length} organizations. Use --org to filter to a specific organization.`);\n }\n }\n \n if (options.debug) {\n const executeDuration = Number(process.hrtime.bigint() - executeStartTime) / 1000000;\n console.log(`[DEBUG] ViewerBuildsCommandHandler execution completed in ${executeDuration.toFixed(2)}ms`);\n }\n \n // Restore original console.debug\n console.debug = originalDebug;\n } catch (error: any) {\n // Restore original console.debug in case of error\n console.debug = originalDebug;\n \n console.error('Error fetching builds:');\n this.handleError(error, options.debug);\n \n // Show additional debug info\n if (options.debug) {\n console.error('ViewerBuildsCommandHandler Error Details:', error);\n }\n \n process.exit(1);\n }\n }\n}"]}
|
|
@@ -0,0 +1,46 @@
|
|
|
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_VIEWER } from '../graphql/queries.js';
|
|
12
|
+
import { getViewerFormatter } from '../formatters/index.js';
|
|
13
|
+
export class ViewerCommandHandler extends BaseCommandHandler {
|
|
14
|
+
constructor(token, options) {
|
|
15
|
+
super(token, options);
|
|
16
|
+
}
|
|
17
|
+
execute(options) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
try {
|
|
20
|
+
// Ensure initialization is complete
|
|
21
|
+
yield this.ensureInitialized();
|
|
22
|
+
const data = yield this.client.query(GET_VIEWER);
|
|
23
|
+
// Check if we have the expected data structure
|
|
24
|
+
if (!(data === null || data === void 0 ? void 0 : data.viewer)) {
|
|
25
|
+
throw new Error('Invalid response format: missing viewer data');
|
|
26
|
+
}
|
|
27
|
+
// Get the formatter based on the format option
|
|
28
|
+
const format = options.format || 'plain';
|
|
29
|
+
const formatter = getViewerFormatter(format);
|
|
30
|
+
const output = formatter.formatViewer(data, { debug: options.debug });
|
|
31
|
+
// Print the output
|
|
32
|
+
console.log(output);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error('Error fetching user information:');
|
|
36
|
+
this.handleError(error, options.debug);
|
|
37
|
+
// Show additional debug info specific to this command
|
|
38
|
+
if (options.debug) {
|
|
39
|
+
console.error('Query:', GET_VIEWER);
|
|
40
|
+
}
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=ViewerCommandHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ViewerCommandHandler.js","sourceRoot":"/","sources":["commands/ViewerCommandHandler.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,kBAAkB,EAAsB,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAM5D,MAAM,OAAO,oBAAqB,SAAQ,kBAAkB;IAC1D,YAAY,KAAa,EAAE,OAAgC;QACzD,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACxB,CAAC;IAEK,OAAO,CAAC,OAAsB;;YAClC,IAAI,CAAC;gBACH,oCAAoC;gBACpC,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAE/B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAa,UAAU,CAAC,CAAC;gBAE7D,+CAA+C;gBAC/C,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,MAAM,CAAA,EAAE,CAAC;oBAClB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;gBAClE,CAAC;gBAED,+CAA+C;gBAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC;gBACzC,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;gBAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;gBAEtE,mBAAmB;gBACnB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACtB,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBAClD,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;gBAEvC,sDAAsD;gBACtD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;oBAClB,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;gBACtC,CAAC;gBAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;KAAA;CACF","sourcesContent":["import { BaseCommandHandler, BaseCommandOptions } from './BaseCommandHandler.js';\nimport { GET_VIEWER } from '../graphql/queries.js';\nimport { getViewerFormatter } from '../formatters/index.js';\nimport { ViewerData } from '../types/index.js';\n\nexport interface ViewerOptions extends BaseCommandOptions {\n}\n\nexport class ViewerCommandHandler extends BaseCommandHandler {\n constructor(token: string, options?: Partial<ViewerOptions>) {\n super(token, options);\n }\n \n async execute(options: ViewerOptions): Promise<void> {\n try {\n // Ensure initialization is complete\n await this.ensureInitialized();\n \n const data = await this.client.query<ViewerData>(GET_VIEWER);\n \n // Check if we have the expected data structure\n if (!data?.viewer) {\n throw new Error('Invalid response format: missing viewer data');\n }\n \n // Get the formatter based on the format option\n const format = options.format || 'plain';\n const formatter = getViewerFormatter(format);\n const output = formatter.formatViewer(data, { debug: options.debug });\n \n // Print the output\n console.log(output);\n } catch (error: any) {\n console.error('Error fetching user information:');\n this.handleError(error, options.debug);\n \n // Show additional debug info specific to this command\n if (options.debug) {\n console.error('Query:', GET_VIEWER);\n }\n \n process.exit(1);\n }\n }\n} "]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './BaseCommand.js';
|
|
2
|
+
export * from './ShowViewer.js';
|
|
3
|
+
export * from './ListOrganizations.js';
|
|
4
|
+
export * from './ListBuilds.js';
|
|
5
|
+
export * from './ListPipelines.js';
|
|
6
|
+
export * from './ManageToken.js';
|
|
7
|
+
export * from './ListAnnotations.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"/","sources":["commands/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC","sourcesContent":["export * from './BaseCommand.js';\nexport * from './ShowViewer.js';\nexport * from './ListOrganizations.js';\nexport * from './ListBuilds.js';\nexport * from './ListPipelines.js';\nexport * from './ManageToken.js';\nexport * from './ListAnnotations.js'; "]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { logger } from '../services/logger.js';
|
|
2
|
+
export class AbstractFormatter {
|
|
3
|
+
name;
|
|
4
|
+
constructor(name) {
|
|
5
|
+
this.name = name;
|
|
6
|
+
}
|
|
7
|
+
format(data, formatFn, options) {
|
|
8
|
+
if (options?.debug) {
|
|
9
|
+
logger.debug(`Formatting with ${this.name} formatter`);
|
|
10
|
+
}
|
|
11
|
+
return formatFn(data, options);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=BaseFormatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseFormatter.js","sourceRoot":"/","sources":["formatters/BaseFormatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAqB/C,MAAM,OAAgB,iBAAiB;IACrC,IAAI,CAAS;IAEb,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,MAAM,CAAI,IAAS,EAAE,QAA2B,EAAE,OAA0B;QAC1E,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;YACnB,MAAM,CAAC,KAAK,CAAC,mBAAmB,IAAI,CAAC,IAAI,YAAY,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;CACF","sourcesContent":["import { logger } from '../services/logger.js';\n\nexport interface FormatterOptions {\n debug?: boolean;\n organizationsCount?: number;\n orgSpecified?: boolean;\n // User information for more specific no-results messages\n userName?: string;\n userEmail?: string;\n userId?: string;\n}\n\nexport interface FormatFunction<T> {\n (data: T[], options?: FormatterOptions): string;\n}\n\nexport interface BaseFormatter {\n name: string;\n format<T>(data: T[], formatFn: FormatFunction<T>, options?: FormatterOptions): string;\n}\n\nexport abstract class AbstractFormatter implements BaseFormatter {\n name: string;\n\n constructor(name: string) {\n this.name = name;\n }\n\n format<T>(data: T[], formatFn: FormatFunction<T>, options?: FormatterOptions): string {\n if (options?.debug) {\n logger.debug(`Formatting with ${this.name} formatter`);\n }\n return formatFn(data, options);\n }\n} "]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { getPipelineFormatter } from './pipelines/index.js';
|
|
2
|
+
import { getBuildFormatter } from './builds/index.js';
|
|
3
|
+
import { getViewerFormatter } from './viewer/index.js';
|
|
4
|
+
import { getOrganizationFormatter } from './organizations/index.js';
|
|
5
|
+
import { getErrorFormatter } from './errors/index.js';
|
|
6
|
+
import { getTokenFormatter } from './token/index.js';
|
|
7
|
+
import { getAnnotationFormatter } from './annotations/index.js';
|
|
8
|
+
export var FormatterType;
|
|
9
|
+
(function (FormatterType) {
|
|
10
|
+
FormatterType["PIPELINE"] = "pipeline";
|
|
11
|
+
FormatterType["BUILD"] = "build";
|
|
12
|
+
FormatterType["VIEWER"] = "viewer";
|
|
13
|
+
FormatterType["ORGANIZATION"] = "organization";
|
|
14
|
+
FormatterType["ERROR"] = "error";
|
|
15
|
+
FormatterType["TOKEN"] = "token";
|
|
16
|
+
FormatterType["ANNOTATION"] = "annotation";
|
|
17
|
+
})(FormatterType || (FormatterType = {}));
|
|
18
|
+
export class FormatterFactory {
|
|
19
|
+
/**
|
|
20
|
+
* Get the appropriate formatter based on the type and format
|
|
21
|
+
* @param type The formatter type ('pipeline', 'build', 'viewer', 'organization', 'error', 'token', 'annotation')
|
|
22
|
+
* @param format The format to use ('plain', 'json', 'alfred')
|
|
23
|
+
* @returns The appropriate formatter instance
|
|
24
|
+
*/
|
|
25
|
+
static getFormatter(type, format = 'plain') {
|
|
26
|
+
// Normalize the format string
|
|
27
|
+
const normalizedFormat = format.toLowerCase().trim();
|
|
28
|
+
switch (type) {
|
|
29
|
+
case FormatterType.PIPELINE:
|
|
30
|
+
return getPipelineFormatter(normalizedFormat);
|
|
31
|
+
case FormatterType.BUILD:
|
|
32
|
+
return getBuildFormatter(normalizedFormat);
|
|
33
|
+
case FormatterType.VIEWER:
|
|
34
|
+
return getViewerFormatter(normalizedFormat);
|
|
35
|
+
case FormatterType.ORGANIZATION:
|
|
36
|
+
return getOrganizationFormatter(normalizedFormat);
|
|
37
|
+
case FormatterType.ERROR:
|
|
38
|
+
return getErrorFormatter(normalizedFormat);
|
|
39
|
+
case FormatterType.TOKEN:
|
|
40
|
+
return getTokenFormatter(normalizedFormat);
|
|
41
|
+
case FormatterType.ANNOTATION:
|
|
42
|
+
return getAnnotationFormatter(normalizedFormat);
|
|
43
|
+
default:
|
|
44
|
+
throw new Error(`Unknown formatter type: ${type}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=FormatterFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormatterFactory.js","sourceRoot":"/","sources":["formatters/FormatterFactory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,MAAM,CAAN,IAAY,aAQX;AARD,WAAY,aAAa;IACvB,sCAAqB,CAAA;IACrB,gCAAe,CAAA;IACf,kCAAiB,CAAA;IACjB,8CAA6B,CAAA;IAC7B,gCAAe,CAAA;IACf,gCAAe,CAAA;IACf,0CAAyB,CAAA;AAC3B,CAAC,EARW,aAAa,KAAb,aAAa,QAQxB;AAED,MAAM,OAAO,gBAAgB;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,YAAY,CAAC,IAAmB,EAAE,SAAiB,OAAO;QAC/D,8BAA8B;QAC9B,MAAM,gBAAgB,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QAErD,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,aAAa,CAAC,QAAQ;gBACzB,OAAO,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;YAChD,KAAK,aAAa,CAAC,KAAK;gBACtB,OAAO,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;YAC7C,KAAK,aAAa,CAAC,MAAM;gBACvB,OAAO,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;YAC9C,KAAK,aAAa,CAAC,YAAY;gBAC7B,OAAO,wBAAwB,CAAC,gBAAgB,CAAC,CAAC;YACpD,KAAK,aAAa,CAAC,KAAK;gBACtB,OAAO,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;YAC7C,KAAK,aAAa,CAAC,KAAK;gBACtB,OAAO,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;YAC7C,KAAK,aAAa,CAAC,UAAU;gBAC3B,OAAO,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;YAClD;gBACE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF","sourcesContent":["import { BaseFormatter } from './BaseFormatter.js';\nimport { getPipelineFormatter } from './pipelines/index.js';\nimport { getBuildFormatter } from './builds/index.js';\nimport { getViewerFormatter } from './viewer/index.js';\nimport { getOrganizationFormatter } from './organizations/index.js';\nimport { getErrorFormatter } from './errors/index.js';\nimport { getTokenFormatter } from './token/index.js';\nimport { getAnnotationFormatter } from './annotations/index.js';\n\nexport enum FormatterType {\n PIPELINE = 'pipeline',\n BUILD = 'build', \n VIEWER = 'viewer',\n ORGANIZATION = 'organization',\n ERROR = 'error',\n TOKEN = 'token',\n ANNOTATION = 'annotation'\n}\n\nexport class FormatterFactory {\n /**\n * Get the appropriate formatter based on the type and format\n * @param type The formatter type ('pipeline', 'build', 'viewer', 'organization', 'error', 'token', 'annotation')\n * @param format The format to use ('plain', 'json', 'alfred')\n * @returns The appropriate formatter instance\n */\n static getFormatter(type: FormatterType, format: string = 'plain'): BaseFormatter {\n // Normalize the format string\n const normalizedFormat = format.toLowerCase().trim();\n \n switch (type) {\n case FormatterType.PIPELINE:\n return getPipelineFormatter(normalizedFormat);\n case FormatterType.BUILD:\n return getBuildFormatter(normalizedFormat);\n case FormatterType.VIEWER:\n return getViewerFormatter(normalizedFormat);\n case FormatterType.ORGANIZATION:\n return getOrganizationFormatter(normalizedFormat);\n case FormatterType.ERROR:\n return getErrorFormatter(normalizedFormat);\n case FormatterType.TOKEN:\n return getTokenFormatter(normalizedFormat);\n case FormatterType.ANNOTATION:\n return getAnnotationFormatter(normalizedFormat);\n default:\n throw new Error(`Unknown formatter type: ${type}`);\n }\n }\n} "]}
|