bktide 1.0.1755547716 → 1.0.1755568192

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 (33) hide show
  1. package/dist/commands/ShowBuild.js +92 -0
  2. package/dist/commands/ShowBuild.js.map +1 -0
  3. package/dist/commands/index.js +1 -0
  4. package/dist/commands/index.js.map +1 -1
  5. package/dist/formatters/FormatterFactory.js +4 -0
  6. package/dist/formatters/FormatterFactory.js.map +1 -1
  7. package/dist/formatters/build-detail/AlfredFormatter.js +113 -0
  8. package/dist/formatters/build-detail/AlfredFormatter.js.map +1 -0
  9. package/dist/formatters/build-detail/Formatter.js +3 -0
  10. package/dist/formatters/build-detail/Formatter.js.map +1 -0
  11. package/dist/formatters/build-detail/JsonFormatter.js +132 -0
  12. package/dist/formatters/build-detail/JsonFormatter.js.map +1 -0
  13. package/dist/formatters/build-detail/PlainTextFormatter.js +851 -0
  14. package/dist/formatters/build-detail/PlainTextFormatter.js.map +1 -0
  15. package/dist/formatters/build-detail/index.js +21 -0
  16. package/dist/formatters/build-detail/index.js.map +1 -0
  17. package/dist/formatters/builds/PlainTextFormatter.js +4 -2
  18. package/dist/formatters/builds/PlainTextFormatter.js.map +1 -1
  19. package/dist/formatters/pipelines/PlainTextFormatter.js +3 -6
  20. package/dist/formatters/pipelines/PlainTextFormatter.js.map +1 -1
  21. package/dist/graphql/queries.js +185 -0
  22. package/dist/graphql/queries.js.map +1 -1
  23. package/dist/index.js +22 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/services/BuildkiteClient.js +87 -26
  26. package/dist/services/BuildkiteClient.js.map +1 -1
  27. package/dist/services/BuildkiteRestClient.js +8 -7
  28. package/dist/services/BuildkiteRestClient.js.map +1 -1
  29. package/dist/ui/theme.js +193 -8
  30. package/dist/ui/theme.js.map +1 -1
  31. package/dist/utils/terminal-links.js +165 -0
  32. package/dist/utils/terminal-links.js.map +1 -0
  33. package/package.json +2 -1
@@ -0,0 +1,92 @@
1
+ import { BaseCommand } from './BaseCommand.js';
2
+ import { logger } from '../services/logger.js';
3
+ import { parseBuildRef } from '../utils/parseBuildRef.js';
4
+ import { FormatterFactory, FormatterType } from '../formatters/index.js';
5
+ import { Progress } from '../ui/progress.js';
6
+ export class ShowBuild extends BaseCommand {
7
+ static requiresToken = true;
8
+ async execute(options) {
9
+ if (options.debug) {
10
+ logger.debug('Starting ShowBuild command execution', options);
11
+ }
12
+ if (!options.buildArg) {
13
+ logger.error('Build reference is required');
14
+ return 1;
15
+ }
16
+ // Adjust options based on implications
17
+ const adjustedOptions = { ...options };
18
+ if (options.failed) {
19
+ adjustedOptions.jobs = true; // --failed implies --jobs
20
+ }
21
+ if (options.annotationsFull) {
22
+ adjustedOptions.annotations = true; // --annotations-full implies --annotations
23
+ }
24
+ if (options.allJobs) {
25
+ adjustedOptions.jobs = true; // --all-jobs implies --jobs
26
+ }
27
+ if (options.full) {
28
+ // --full shows everything
29
+ adjustedOptions.jobs = true;
30
+ adjustedOptions.annotations = true;
31
+ adjustedOptions.allJobs = true; // --full shows all jobs
32
+ }
33
+ // Initialize spinner early
34
+ const format = options.format || 'plain';
35
+ const spinner = Progress.spinner('Fetching build details…', { format });
36
+ try {
37
+ // Ensure the command is initialized
38
+ await this.ensureInitialized();
39
+ // Parse build reference
40
+ const buildRef = parseBuildRef(options.buildArg);
41
+ if (options.debug) {
42
+ logger.debug('Parsed build reference:', buildRef);
43
+ }
44
+ // Construct build slug for GraphQL
45
+ const buildSlug = `${buildRef.org}/${buildRef.pipeline}/${buildRef.number}`;
46
+ // Fetch build data based on what's needed
47
+ const buildData = await this.fetchBuildData(buildSlug, adjustedOptions);
48
+ spinner.stop();
49
+ // Get the appropriate formatter
50
+ const formatter = FormatterFactory.getFormatter(FormatterType.BUILD_DETAIL, options.format || 'plain');
51
+ // Format and output the results
52
+ const output = formatter.formatBuildDetail(buildData, adjustedOptions);
53
+ logger.console(output);
54
+ return 0;
55
+ }
56
+ catch (error) {
57
+ spinner.stop();
58
+ logger.error('Failed to fetch build:', error);
59
+ // Handle the error with the formatter
60
+ const formatter = FormatterFactory.getFormatter(FormatterType.BUILD_DETAIL, options.format || 'plain');
61
+ const errorOutput = formatter.formatBuildDetail(null, {
62
+ ...adjustedOptions,
63
+ hasError: true,
64
+ errorMessage: error instanceof Error ? error.message : 'Unknown error occurred',
65
+ errorType: 'api',
66
+ });
67
+ logger.console(errorOutput);
68
+ return 1;
69
+ }
70
+ }
71
+ async fetchBuildData(buildSlug, options) {
72
+ // Determine what data we need to fetch based on options
73
+ const needsJobs = options.jobs || options.failed || options.full;
74
+ const needsAnnotations = options.annotations || options.annotationsFull || options.full;
75
+ if (options.debug) {
76
+ logger.debug('Fetching build data', {
77
+ buildSlug,
78
+ needsJobs,
79
+ needsAnnotations,
80
+ full: options.full
81
+ });
82
+ }
83
+ // Fetch the appropriate level of detail
84
+ if (options.full || needsJobs) {
85
+ return await this.client.getBuildFull(buildSlug);
86
+ }
87
+ else {
88
+ return await this.client.getBuildSummary(buildSlug);
89
+ }
90
+ }
91
+ }
92
+ //# sourceMappingURL=ShowBuild.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ShowBuild.js","sourceRoot":"/","sources":["commands/ShowBuild.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseCommand, BaseCommandOptions } from './BaseCommand.js';\nimport { logger } from '../services/logger.js';\nimport { parseBuildRef } from '../utils/parseBuildRef.js';\nimport { FormatterFactory, FormatterType } from '../formatters/index.js';\nimport { Progress } from '../ui/progress.js';\n\nexport interface ShowBuildOptions extends BaseCommandOptions {\n jobs?: boolean;\n failed?: boolean;\n annotations?: boolean;\n annotationsFull?: boolean;\n full?: boolean;\n summary?: boolean;\n allJobs?: boolean;\n buildArg?: string;\n}\n\nexport class ShowBuild extends BaseCommand {\n static requiresToken = true;\n\n async execute(options: ShowBuildOptions): Promise<number> {\n if (options.debug) {\n logger.debug('Starting ShowBuild command execution', options);\n }\n \n if (!options.buildArg) {\n logger.error('Build reference is required');\n return 1;\n }\n \n // Adjust options based on implications\n const adjustedOptions = { ...options };\n if (options.failed) {\n adjustedOptions.jobs = true; // --failed implies --jobs\n }\n if (options.annotationsFull) {\n adjustedOptions.annotations = true; // --annotations-full implies --annotations\n }\n if (options.allJobs) {\n adjustedOptions.jobs = true; // --all-jobs implies --jobs\n }\n if (options.full) {\n // --full shows everything\n adjustedOptions.jobs = true;\n adjustedOptions.annotations = true;\n adjustedOptions.allJobs = true; // --full shows all jobs\n }\n \n // Initialize spinner early\n const format = options.format || 'plain';\n const spinner = Progress.spinner('Fetching build details…', { format });\n \n try {\n // Ensure the command is initialized\n await this.ensureInitialized();\n \n // Parse build reference\n const buildRef = parseBuildRef(options.buildArg);\n if (options.debug) {\n logger.debug('Parsed build reference:', buildRef);\n }\n \n // Construct build slug for GraphQL\n const buildSlug = `${buildRef.org}/${buildRef.pipeline}/${buildRef.number}`;\n \n // Fetch build data based on what's needed\n const buildData = await this.fetchBuildData(buildSlug, adjustedOptions);\n spinner.stop();\n \n // Get the appropriate formatter\n const formatter = FormatterFactory.getFormatter(\n FormatterType.BUILD_DETAIL,\n options.format || 'plain'\n ) as any;\n \n // Format and output the results\n const output = formatter.formatBuildDetail(buildData, adjustedOptions);\n \n logger.console(output);\n \n return 0;\n } catch (error) {\n spinner.stop();\n logger.error('Failed to fetch build:', error);\n \n // Handle the error with the formatter\n const formatter = FormatterFactory.getFormatter(\n FormatterType.BUILD_DETAIL,\n options.format || 'plain'\n ) as any;\n \n const errorOutput = formatter.formatBuildDetail(null, {\n ...adjustedOptions,\n hasError: true,\n errorMessage: error instanceof Error ? error.message : 'Unknown error occurred',\n errorType: 'api',\n });\n \n logger.console(errorOutput);\n return 1;\n }\n }\n \n private async fetchBuildData(buildSlug: string, options: ShowBuildOptions): Promise<any> {\n // Determine what data we need to fetch based on options\n const needsJobs = options.jobs || options.failed || options.full;\n const needsAnnotations = options.annotations || options.annotationsFull || options.full;\n \n if (options.debug) {\n logger.debug('Fetching build data', {\n buildSlug,\n needsJobs,\n needsAnnotations,\n full: options.full\n });\n }\n \n // Fetch the appropriate level of detail\n if (options.full || needsJobs) {\n return await this.client.getBuildFull(buildSlug);\n } else {\n return await this.client.getBuildSummary(buildSlug);\n }\n }\n}\n"]}
@@ -6,4 +6,5 @@ export * from './ListPipelines.js';
6
6
  export * from './ManageToken.js';
7
7
  export * from './ListAnnotations.js';
8
8
  export * from './GenerateCompletions.js';
9
+ export * from './ShowBuild.js';
9
10
  //# sourceMappingURL=index.js.map
@@ -1 +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;AACrC,cAAc,0BAA0B,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';\nexport * from './GenerateCompletions.js';"]}
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;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gBAAgB,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';\nexport * from './GenerateCompletions.js';\nexport * from './ShowBuild.js';"]}
@@ -5,6 +5,7 @@ import { getOrganizationFormatter } from './organizations/index.js';
5
5
  import { getErrorFormatter } from './errors/index.js';
6
6
  import { getTokenFormatter } from './token/index.js';
7
7
  import { getAnnotationFormatter } from './annotations/index.js';
8
+ import { getBuildDetailFormatter } from './build-detail/index.js';
8
9
  export var FormatterType;
9
10
  (function (FormatterType) {
10
11
  FormatterType["PIPELINE"] = "pipeline";
@@ -14,6 +15,7 @@ export var FormatterType;
14
15
  FormatterType["ERROR"] = "error";
15
16
  FormatterType["TOKEN"] = "token";
16
17
  FormatterType["ANNOTATION"] = "annotation";
18
+ FormatterType["BUILD_DETAIL"] = "build-detail";
17
19
  })(FormatterType || (FormatterType = {}));
18
20
  export class FormatterFactory {
19
21
  /**
@@ -40,6 +42,8 @@ export class FormatterFactory {
40
42
  return getTokenFormatter(normalizedFormat);
41
43
  case FormatterType.ANNOTATION:
42
44
  return getAnnotationFormatter(normalizedFormat);
45
+ case FormatterType.BUILD_DETAIL:
46
+ return getBuildDetailFormatter(normalizedFormat);
43
47
  default:
44
48
  throw new Error(`Unknown formatter type: ${type}`);
45
49
  }
@@ -1 +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} "]}
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;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAElE,MAAM,CAAN,IAAY,aASX;AATD,WAAY,aAAa;IACvB,sCAAqB,CAAA;IACrB,gCAAe,CAAA;IACf,kCAAiB,CAAA;IACjB,8CAA6B,CAAA;IAC7B,gCAAe,CAAA;IACf,gCAAe,CAAA;IACf,0CAAyB,CAAA;IACzB,8CAA6B,CAAA;AAC/B,CAAC,EATW,aAAa,KAAb,aAAa,QASxB;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,KAAK,aAAa,CAAC,YAAY;gBAC7B,OAAO,uBAAuB,CAAC,gBAAgB,CAAQ,CAAC;YAC1D;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';\nimport { getBuildDetailFormatter } from './build-detail/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 BUILD_DETAIL = 'build-detail'\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 case FormatterType.BUILD_DETAIL:\n return getBuildDetailFormatter(normalizedFormat) as any;\n default:\n throw new Error(`Unknown formatter type: ${type}`);\n }\n }\n} "]}
@@ -0,0 +1,113 @@
1
+ import { BaseBuildDetailFormatter } from './Formatter.js';
2
+ export class AlfredFormatter extends BaseBuildDetailFormatter {
3
+ name = 'alfred';
4
+ formatBuildDetail(buildData, options) {
5
+ if (options?.hasError || !buildData) {
6
+ return JSON.stringify({
7
+ items: [{
8
+ uid: 'error',
9
+ title: 'Error fetching build',
10
+ subtitle: options?.errorMessage || 'An error occurred',
11
+ valid: false,
12
+ icon: {
13
+ path: './icons/error.png'
14
+ }
15
+ }]
16
+ });
17
+ }
18
+ const build = buildData.build;
19
+ const items = [];
20
+ // Main build item
21
+ const duration = this.formatDuration(build);
22
+ const mainItem = {
23
+ uid: build.id,
24
+ title: `#${build.number}: ${build.message || 'No message'}`,
25
+ subtitle: `${build.state} • ${build.branch} • ${duration}`,
26
+ arg: build.url,
27
+ icon: {
28
+ path: this.getIconPath(build.state)
29
+ },
30
+ mods: {
31
+ cmd: {
32
+ subtitle: 'Open in browser',
33
+ arg: build.url
34
+ },
35
+ alt: {
36
+ subtitle: 'Copy build number',
37
+ arg: build.number.toString()
38
+ }
39
+ }
40
+ };
41
+ items.push(mainItem);
42
+ // Add failed jobs if present
43
+ if (options?.failed || build.state === 'FAILED') {
44
+ const failedJobs = (build.jobs?.edges || [])
45
+ .filter((j) => j.node.state === 'FAILED' || j.node.exitStatus !== 0);
46
+ for (const job of failedJobs) {
47
+ items.push({
48
+ uid: job.node.id,
49
+ title: `❌ ${job.node.label}`,
50
+ subtitle: `Failed with exit code ${job.node.exitStatus || 1}`,
51
+ valid: false,
52
+ icon: {
53
+ path: './icons/failed.png'
54
+ }
55
+ });
56
+ }
57
+ }
58
+ // Add annotation summary if present
59
+ if (build.annotations?.edges?.length > 0) {
60
+ const annotationCount = build.annotations.edges.length;
61
+ items.push({
62
+ uid: 'annotations',
63
+ title: `📝 ${annotationCount} annotation${annotationCount > 1 ? 's' : ''}`,
64
+ subtitle: 'View build annotations',
65
+ valid: false,
66
+ icon: {
67
+ path: './icons/annotation.png'
68
+ }
69
+ });
70
+ }
71
+ return JSON.stringify({ items });
72
+ }
73
+ formatDuration(build) {
74
+ if (!build.startedAt) {
75
+ return 'not started';
76
+ }
77
+ const start = new Date(build.startedAt);
78
+ const end = build.finishedAt ? new Date(build.finishedAt) : new Date();
79
+ const durationMs = end.getTime() - start.getTime();
80
+ const minutes = Math.floor(durationMs / 60000);
81
+ const seconds = Math.floor((durationMs % 60000) / 1000);
82
+ if (build.state === 'RUNNING') {
83
+ return `${minutes}m ${seconds}s elapsed`;
84
+ }
85
+ return `${minutes}m ${seconds}s`;
86
+ }
87
+ getIconPath(state) {
88
+ const iconMap = {
89
+ 'PASSED': './icons/passed.png',
90
+ 'FAILED': './icons/failed.png',
91
+ 'RUNNING': './icons/running.png',
92
+ 'BLOCKED': './icons/blocked.png',
93
+ 'CANCELED': './icons/canceled.png',
94
+ 'SCHEDULED': './icons/scheduled.png',
95
+ 'SKIPPED': './icons/skipped.png'
96
+ };
97
+ return iconMap[state] || './icons/unknown.png';
98
+ }
99
+ formatError(action, error) {
100
+ return JSON.stringify({
101
+ items: [{
102
+ uid: 'error',
103
+ title: `Error ${action}`,
104
+ subtitle: error instanceof Error ? error.message : String(error),
105
+ valid: false,
106
+ icon: {
107
+ path: './icons/error.png'
108
+ }
109
+ }]
110
+ });
111
+ }
112
+ }
113
+ //# sourceMappingURL=AlfredFormatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AlfredFormatter.js","sourceRoot":"/","sources":["formatters/build-detail/AlfredFormatter.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseBuildDetailFormatter, BuildDetail, BuildDetailFormatterOptions } from './Formatter.js';\n\nexport class AlfredFormatter extends BaseBuildDetailFormatter {\n name = 'alfred';\n \n formatBuildDetail(buildData: BuildDetail | null, options?: BuildDetailFormatterOptions): string {\n if (options?.hasError || !buildData) {\n return JSON.stringify({\n items: [{\n uid: 'error',\n title: 'Error fetching build',\n subtitle: options?.errorMessage || 'An error occurred',\n valid: false,\n icon: {\n path: './icons/error.png'\n }\n }]\n });\n }\n \n const build = buildData.build;\n const items: any[] = [];\n \n // Main build item\n const duration = this.formatDuration(build);\n const mainItem = {\n uid: build.id,\n title: `#${build.number}: ${build.message || 'No message'}`,\n subtitle: `${build.state} • ${build.branch} • ${duration}`,\n arg: build.url,\n icon: {\n path: this.getIconPath(build.state)\n },\n mods: {\n cmd: {\n subtitle: 'Open in browser',\n arg: build.url\n },\n alt: {\n subtitle: 'Copy build number',\n arg: build.number.toString()\n }\n }\n };\n \n items.push(mainItem);\n \n // Add failed jobs if present\n if (options?.failed || build.state === 'FAILED') {\n const failedJobs = (build.jobs?.edges || [])\n .filter((j: any) => j.node.state === 'FAILED' || j.node.exitStatus !== 0);\n \n for (const job of failedJobs) {\n items.push({\n uid: job.node.id,\n title: `❌ ${job.node.label}`,\n subtitle: `Failed with exit code ${job.node.exitStatus || 1}`,\n valid: false,\n icon: {\n path: './icons/failed.png'\n }\n });\n }\n }\n \n // Add annotation summary if present\n if (build.annotations?.edges?.length > 0) {\n const annotationCount = build.annotations.edges.length;\n items.push({\n uid: 'annotations',\n title: `📝 ${annotationCount} annotation${annotationCount > 1 ? 's' : ''}`,\n subtitle: 'View build annotations',\n valid: false,\n icon: {\n path: './icons/annotation.png'\n }\n });\n }\n \n return JSON.stringify({ items });\n }\n \n private formatDuration(build: any): string {\n if (!build.startedAt) {\n return 'not started';\n }\n \n const start = new Date(build.startedAt);\n const end = build.finishedAt ? new Date(build.finishedAt) : new Date();\n const durationMs = end.getTime() - start.getTime();\n \n const minutes = Math.floor(durationMs / 60000);\n const seconds = Math.floor((durationMs % 60000) / 1000);\n \n if (build.state === 'RUNNING') {\n return `${minutes}m ${seconds}s elapsed`;\n }\n \n return `${minutes}m ${seconds}s`;\n }\n \n private getIconPath(state: string): string {\n const iconMap: Record<string, string> = {\n 'PASSED': './icons/passed.png',\n 'FAILED': './icons/failed.png',\n 'RUNNING': './icons/running.png',\n 'BLOCKED': './icons/blocked.png',\n 'CANCELED': './icons/canceled.png',\n 'SCHEDULED': './icons/scheduled.png',\n 'SKIPPED': './icons/skipped.png'\n };\n \n return iconMap[state] || './icons/unknown.png';\n }\n \n formatError(action: string, error: any): string {\n return JSON.stringify({\n items: [{\n uid: 'error',\n title: `Error ${action}`,\n subtitle: error instanceof Error ? error.message : String(error),\n valid: false,\n icon: {\n path: './icons/error.png'\n }\n }]\n });\n }\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export class BaseBuildDetailFormatter {
2
+ }
3
+ //# sourceMappingURL=Formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Formatter.js","sourceRoot":"/","sources":["formatters/build-detail/Formatter.ts"],"names":[],"mappings":"AAcA,MAAM,OAAgB,wBAAwB;CAI7C","sourcesContent":["import { ShowBuildOptions } from '../../commands/ShowBuild.js';\n\nexport interface BuildDetail {\n build: any;\n jobs?: any[];\n annotations?: any[];\n}\n\nexport interface BuildDetailFormatterOptions extends ShowBuildOptions {\n hasError?: boolean;\n errorMessage?: string;\n errorType?: 'access' | 'not_found' | 'api';\n}\n\nexport abstract class BaseBuildDetailFormatter {\n abstract name: string;\n abstract formatBuildDetail(buildData: BuildDetail | null, options?: BuildDetailFormatterOptions): string;\n abstract formatError(action: string, error: any): string;\n}\n"]}
@@ -0,0 +1,132 @@
1
+ import { BaseBuildDetailFormatter } from './Formatter.js';
2
+ export class JsonFormatter extends BaseBuildDetailFormatter {
3
+ name = 'json';
4
+ formatBuildDetail(buildData, options) {
5
+ if (options?.hasError || !buildData) {
6
+ return JSON.stringify({
7
+ error: true,
8
+ errorType: options?.errorType || 'unknown',
9
+ message: options?.errorMessage || 'An error occurred'
10
+ }, null, 2);
11
+ }
12
+ const build = buildData.build;
13
+ // Transform based on options
14
+ let output = {
15
+ id: build.id,
16
+ number: build.number,
17
+ state: build.state,
18
+ branch: build.branch,
19
+ message: build.message,
20
+ commit: build.commit,
21
+ url: build.url,
22
+ createdAt: build.createdAt,
23
+ startedAt: build.startedAt,
24
+ finishedAt: build.finishedAt
25
+ };
26
+ // Add creator info
27
+ if (build.createdBy) {
28
+ output.createdBy = {
29
+ name: build.createdBy.name,
30
+ email: build.createdBy.email
31
+ };
32
+ }
33
+ // Add organization and pipeline
34
+ if (build.organization) {
35
+ output.organization = {
36
+ id: build.organization.id,
37
+ name: build.organization.name,
38
+ slug: build.organization.slug
39
+ };
40
+ }
41
+ if (build.pipeline) {
42
+ output.pipeline = {
43
+ id: build.pipeline.id,
44
+ name: build.pipeline.name,
45
+ slug: build.pipeline.slug
46
+ };
47
+ }
48
+ // Add jobs if requested or failed
49
+ if (options?.jobs || options?.failed || options?.full) {
50
+ const jobs = build.jobs?.edges || [];
51
+ if (options?.failed) {
52
+ // Filter to only failed jobs
53
+ output.jobs = jobs
54
+ .filter((j) => j.node.state === 'FAILED' || j.node.exitStatus !== 0)
55
+ .map((j) => this.formatJob(j.node));
56
+ }
57
+ else {
58
+ output.jobs = jobs.map((j) => this.formatJob(j.node));
59
+ }
60
+ }
61
+ // Add annotations if requested
62
+ if (options?.annotations || options?.annotationsFull || options?.full) {
63
+ const annotations = build.annotations?.edges || [];
64
+ output.annotations = annotations.map((a) => ({
65
+ id: a.node.id,
66
+ style: a.node.style,
67
+ context: a.node.context,
68
+ body: options?.annotationsFull ? a.node.body?.html : undefined,
69
+ createdAt: a.node.createdAt,
70
+ updatedAt: a.node.updatedAt
71
+ }));
72
+ }
73
+ // Add extra details if full
74
+ if (options?.full) {
75
+ if (build.pullRequest) {
76
+ output.pullRequest = {
77
+ id: build.pullRequest.id,
78
+ number: build.pullRequest.number,
79
+ repository: build.pullRequest.repository
80
+ };
81
+ }
82
+ if (build.triggeredFrom) {
83
+ output.triggeredFrom = {
84
+ id: build.triggeredFrom.id,
85
+ number: build.triggeredFrom.number,
86
+ url: build.triggeredFrom.url,
87
+ pipeline: build.triggeredFrom.pipeline
88
+ };
89
+ }
90
+ if (build.blockedState) {
91
+ output.blockedState = build.blockedState;
92
+ }
93
+ }
94
+ return JSON.stringify(output, null, 2);
95
+ }
96
+ formatJob(job) {
97
+ const formatted = {
98
+ id: job.id,
99
+ uuid: job.uuid,
100
+ label: job.label,
101
+ state: job.state,
102
+ exitStatus: job.exitStatus,
103
+ passed: job.passed,
104
+ soft_failed: job.soft_failed,
105
+ startedAt: job.startedAt,
106
+ finishedAt: job.finishedAt
107
+ };
108
+ if (job.command) {
109
+ formatted.command = job.command;
110
+ }
111
+ if (job.agent) {
112
+ formatted.agent = {
113
+ id: job.agent.id,
114
+ name: job.agent.name,
115
+ hostname: job.agent.hostname
116
+ };
117
+ }
118
+ if (job.retried !== undefined) {
119
+ formatted.retried = job.retried;
120
+ }
121
+ return formatted;
122
+ }
123
+ formatError(action, error) {
124
+ return JSON.stringify({
125
+ error: true,
126
+ action,
127
+ message: error instanceof Error ? error.message : String(error),
128
+ timestamp: new Date().toISOString()
129
+ }, null, 2);
130
+ }
131
+ }
132
+ //# sourceMappingURL=JsonFormatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonFormatter.js","sourceRoot":"/","sources":["formatters/build-detail/JsonFormatter.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseBuildDetailFormatter, BuildDetail, BuildDetailFormatterOptions } from './Formatter.js';\n\nexport class JsonFormatter extends BaseBuildDetailFormatter {\n name = 'json';\n \n formatBuildDetail(buildData: BuildDetail | null, options?: BuildDetailFormatterOptions): string {\n if (options?.hasError || !buildData) {\n return JSON.stringify({\n error: true,\n errorType: options?.errorType || 'unknown',\n message: options?.errorMessage || 'An error occurred'\n }, null, 2);\n }\n \n const build = buildData.build;\n \n // Transform based on options\n let output: any = {\n id: build.id,\n number: build.number,\n state: build.state,\n branch: build.branch,\n message: build.message,\n commit: build.commit,\n url: build.url,\n createdAt: build.createdAt,\n startedAt: build.startedAt,\n finishedAt: build.finishedAt\n };\n \n // Add creator info\n if (build.createdBy) {\n output.createdBy = {\n name: build.createdBy.name,\n email: build.createdBy.email\n };\n }\n \n // Add organization and pipeline\n if (build.organization) {\n output.organization = {\n id: build.organization.id,\n name: build.organization.name,\n slug: build.organization.slug\n };\n }\n \n if (build.pipeline) {\n output.pipeline = {\n id: build.pipeline.id,\n name: build.pipeline.name,\n slug: build.pipeline.slug\n };\n }\n \n // Add jobs if requested or failed\n if (options?.jobs || options?.failed || options?.full) {\n const jobs = build.jobs?.edges || [];\n \n if (options?.failed) {\n // Filter to only failed jobs\n output.jobs = jobs\n .filter((j: any) => j.node.state === 'FAILED' || j.node.exitStatus !== 0)\n .map((j: any) => this.formatJob(j.node));\n } else {\n output.jobs = jobs.map((j: any) => this.formatJob(j.node));\n }\n }\n \n // Add annotations if requested\n if (options?.annotations || options?.annotationsFull || options?.full) {\n const annotations = build.annotations?.edges || [];\n output.annotations = annotations.map((a: any) => ({\n id: a.node.id,\n style: a.node.style,\n context: a.node.context,\n body: options?.annotationsFull ? a.node.body?.html : undefined,\n createdAt: a.node.createdAt,\n updatedAt: a.node.updatedAt\n }));\n }\n \n // Add extra details if full\n if (options?.full) {\n if (build.pullRequest) {\n output.pullRequest = {\n id: build.pullRequest.id,\n number: build.pullRequest.number,\n repository: build.pullRequest.repository\n };\n }\n \n if (build.triggeredFrom) {\n output.triggeredFrom = {\n id: build.triggeredFrom.id,\n number: build.triggeredFrom.number,\n url: build.triggeredFrom.url,\n pipeline: build.triggeredFrom.pipeline\n };\n }\n \n if (build.blockedState) {\n output.blockedState = build.blockedState;\n }\n }\n \n return JSON.stringify(output, null, 2);\n }\n \n private formatJob(job: any): any {\n const formatted: any = {\n id: job.id,\n uuid: job.uuid,\n label: job.label,\n state: job.state,\n exitStatus: job.exitStatus,\n passed: job.passed,\n soft_failed: job.soft_failed,\n startedAt: job.startedAt,\n finishedAt: job.finishedAt\n };\n \n if (job.command) {\n formatted.command = job.command;\n }\n \n if (job.agent) {\n formatted.agent = {\n id: job.agent.id,\n name: job.agent.name,\n hostname: job.agent.hostname\n };\n }\n \n if (job.retried !== undefined) {\n formatted.retried = job.retried;\n }\n \n return formatted;\n }\n \n formatError(action: string, error: any): string {\n return JSON.stringify({\n error: true,\n action,\n message: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString()\n }, null, 2);\n }\n}\n"]}