bktide 1.0.1755267617 → 1.0.1755559112
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -1
- package/WORKFLOW_README.md +1 -1
- package/completions/bktide-dynamic.fish +171 -0
- package/completions/bktide.bash +124 -0
- package/completions/bktide.fish +107 -0
- package/completions/bktide.zsh +139 -0
- package/dist/commands/BaseCommand.js +7 -7
- package/dist/commands/BaseCommand.js.map +1 -1
- package/dist/commands/GenerateCompletions.js +238 -0
- package/dist/commands/GenerateCompletions.js.map +1 -0
- package/dist/commands/ListAnnotations.js +7 -0
- package/dist/commands/ListAnnotations.js.map +1 -1
- package/dist/commands/ListBuilds.js +67 -3
- package/dist/commands/ListBuilds.js.map +1 -1
- package/dist/commands/ListOrganizations.js +6 -0
- package/dist/commands/ListOrganizations.js.map +1 -1
- package/dist/commands/ListPipelines.js +87 -12
- package/dist/commands/ListPipelines.js.map +1 -1
- package/dist/commands/ManageToken.js +32 -9
- package/dist/commands/ManageToken.js.map +1 -1
- package/dist/commands/ShowBuild.js +88 -0
- package/dist/commands/ShowBuild.js.map +1 -0
- package/dist/commands/ShowViewer.js +7 -1
- package/dist/commands/ShowViewer.js.map +1 -1
- package/dist/commands/index.js +2 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/formatters/FormatterFactory.js +4 -0
- package/dist/formatters/FormatterFactory.js.map +1 -1
- package/dist/formatters/annotations/PlainTextFormatter.js +37 -9
- package/dist/formatters/annotations/PlainTextFormatter.js.map +1 -1
- package/dist/formatters/build-detail/AlfredFormatter.js +113 -0
- package/dist/formatters/build-detail/AlfredFormatter.js.map +1 -0
- package/dist/formatters/build-detail/Formatter.js +3 -0
- package/dist/formatters/build-detail/Formatter.js.map +1 -0
- package/dist/formatters/build-detail/JsonFormatter.js +132 -0
- package/dist/formatters/build-detail/JsonFormatter.js.map +1 -0
- package/dist/formatters/build-detail/PlainTextFormatter.js +680 -0
- package/dist/formatters/build-detail/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/build-detail/index.js +21 -0
- package/dist/formatters/build-detail/index.js.map +1 -0
- package/dist/formatters/builds/PlainTextFormatter.js +82 -60
- package/dist/formatters/builds/PlainTextFormatter.js.map +1 -1
- package/dist/formatters/errors/AlfredFormatter.js +20 -0
- package/dist/formatters/errors/AlfredFormatter.js.map +1 -1
- package/dist/formatters/errors/PlainTextFormatter.js +121 -23
- package/dist/formatters/errors/PlainTextFormatter.js.map +1 -1
- package/dist/formatters/organizations/PlainTextFormatter.js +37 -6
- package/dist/formatters/organizations/PlainTextFormatter.js.map +1 -1
- package/dist/formatters/pipelines/AlfredFormatter.js.map +1 -1
- package/dist/formatters/pipelines/Formatter.js.map +1 -1
- package/dist/formatters/pipelines/JsonFormatter.js.map +1 -1
- package/dist/formatters/pipelines/PlainTextFormatter.js +165 -19
- package/dist/formatters/pipelines/PlainTextFormatter.js.map +1 -1
- package/dist/formatters/token/AlfredFormatter.js +15 -2
- package/dist/formatters/token/AlfredFormatter.js.map +1 -1
- package/dist/formatters/token/PlainTextFormatter.js +56 -18
- package/dist/formatters/token/PlainTextFormatter.js.map +1 -1
- package/dist/formatters/viewer/PlainTextFormatter.js +8 -7
- package/dist/formatters/viewer/PlainTextFormatter.js.map +1 -1
- package/dist/graphql/queries.js +181 -0
- package/dist/graphql/queries.js.map +1 -1
- package/dist/index.js +67 -6
- package/dist/index.js.map +1 -1
- package/dist/services/BuildkiteClient.js +61 -1
- package/dist/services/BuildkiteClient.js.map +1 -1
- package/dist/services/CredentialManager.js +80 -10
- package/dist/services/CredentialManager.js.map +1 -1
- package/dist/ui/help.js +69 -0
- package/dist/ui/help.js.map +1 -0
- package/dist/ui/progress.js +356 -0
- package/dist/ui/progress.js.map +1 -0
- package/dist/ui/reporter.js +111 -0
- package/dist/ui/reporter.js.map +1 -0
- package/dist/ui/responsive-table.js +183 -0
- package/dist/ui/responsive-table.js.map +1 -0
- package/dist/ui/spinner.js +20 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/symbols.js +46 -0
- package/dist/ui/symbols.js.map +1 -0
- package/dist/ui/table.js +32 -0
- package/dist/ui/table.js.map +1 -0
- package/dist/ui/theme.js +280 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/ui/width.js +111 -0
- package/dist/ui/width.js.map +1 -0
- package/dist/utils/alfred.js +6 -0
- package/dist/utils/alfred.js.map +1 -0
- package/dist/utils/cli-error-handler.js +35 -20
- package/dist/utils/cli-error-handler.js.map +1 -1
- package/dist/utils/pagination.js +92 -0
- package/dist/utils/pagination.js.map +1 -0
- package/info.plist +51 -218
- package/package.json +24 -5
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#compdef bktide
|
|
2
|
+
# Zsh completions for bktide CLI
|
|
3
|
+
# Install by adding to ~/.zshrc: source <(bktide completions zsh)
|
|
4
|
+
# Or copy to a directory in your $fpath
|
|
5
|
+
|
|
6
|
+
_bktide() {
|
|
7
|
+
local -a commands global_opts
|
|
8
|
+
|
|
9
|
+
commands=(
|
|
10
|
+
'viewer:Show logged in user information'
|
|
11
|
+
'orgs:List organizations'
|
|
12
|
+
'pipelines:List pipelines for an organization'
|
|
13
|
+
'builds:List builds for the current user'
|
|
14
|
+
'token:Manage API tokens'
|
|
15
|
+
'annotations:Show annotations for a build'
|
|
16
|
+
'completions:Generate shell completions'
|
|
17
|
+
'boom:Test error handling'
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
global_opts=(
|
|
21
|
+
'--log-level[Set logging level]:level:(trace debug info warn error fatal)'
|
|
22
|
+
{-d,--debug}'[Show debug information for errors]'
|
|
23
|
+
'--no-cache[Disable caching of API responses]'
|
|
24
|
+
'--cache-ttl[Set cache TTL in milliseconds]:milliseconds:'
|
|
25
|
+
'--clear-cache[Clear all cached data before executing]'
|
|
26
|
+
{-t,--token}'[Buildkite API token]:token:'
|
|
27
|
+
'--save-token[Save the token to system keychain]'
|
|
28
|
+
{-f,--format}'[Output format]:format:(plain json alfred)'
|
|
29
|
+
'--color[Color output mode]:mode:(auto always never)'
|
|
30
|
+
{-q,--quiet}'[Suppress non-error output]'
|
|
31
|
+
'--tips[Show helpful tips and suggestions]'
|
|
32
|
+
'--no-tips[Hide helpful tips and suggestions]'
|
|
33
|
+
'--ascii[Use ASCII symbols instead of Unicode]'
|
|
34
|
+
{-h,--help}'[Show help]'
|
|
35
|
+
{-V,--version}'[Show version]'
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Main command completion
|
|
39
|
+
if (( CURRENT == 2 )); then
|
|
40
|
+
_describe -t commands 'bktide commands' commands
|
|
41
|
+
return
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
local cmd="${words[2]}"
|
|
45
|
+
|
|
46
|
+
# Command-specific completions
|
|
47
|
+
case "$cmd" in
|
|
48
|
+
pipelines)
|
|
49
|
+
_arguments \
|
|
50
|
+
{-o,--org}'[Organization slug]:org:->orgs' \
|
|
51
|
+
{-n,--count}'[Limit to specified number]:count:' \
|
|
52
|
+
'--filter[Filter pipelines by name]:filter:' \
|
|
53
|
+
$global_opts
|
|
54
|
+
|
|
55
|
+
case "$state" in
|
|
56
|
+
orgs)
|
|
57
|
+
# Dynamic org completion
|
|
58
|
+
local -a orgs
|
|
59
|
+
orgs=(${(f)"$(bktide orgs --format json --quiet 2>/dev/null | jq -r '.[].slug' 2>/dev/null)"})
|
|
60
|
+
_describe -t orgs 'organizations' orgs
|
|
61
|
+
;;
|
|
62
|
+
esac
|
|
63
|
+
;;
|
|
64
|
+
|
|
65
|
+
builds)
|
|
66
|
+
_arguments \
|
|
67
|
+
{-o,--org}'[Organization slug]:org:->orgs' \
|
|
68
|
+
{-p,--pipeline}'[Filter by pipeline slug]:pipeline:->pipelines' \
|
|
69
|
+
{-b,--branch}'[Filter by branch name]:branch:->branches' \
|
|
70
|
+
{-s,--state}'[Filter by build state]:state:(running scheduled passed failing failed canceled blocked canceling skipped not_run)' \
|
|
71
|
+
{-n,--count}'[Number of builds per page]:count:' \
|
|
72
|
+
'--page[Page number]:page:' \
|
|
73
|
+
'--filter[Fuzzy filter builds]:filter:' \
|
|
74
|
+
$global_opts
|
|
75
|
+
|
|
76
|
+
case "$state" in
|
|
77
|
+
orgs)
|
|
78
|
+
local -a orgs
|
|
79
|
+
orgs=(${(f)"$(bktide orgs --format json --quiet 2>/dev/null | jq -r '.[].slug' 2>/dev/null)"})
|
|
80
|
+
_describe -t orgs 'organizations' orgs
|
|
81
|
+
;;
|
|
82
|
+
pipelines)
|
|
83
|
+
local -a pipelines
|
|
84
|
+
pipelines=(${(f)"$(bktide pipelines --format json --quiet 2>/dev/null | jq -r '.[].slug' 2>/dev/null)"})
|
|
85
|
+
_describe -t pipelines 'pipelines' pipelines
|
|
86
|
+
;;
|
|
87
|
+
branches)
|
|
88
|
+
local -a branches
|
|
89
|
+
branches=(main master develop staging production)
|
|
90
|
+
if git rev-parse --git-dir &>/dev/null; then
|
|
91
|
+
branches+=(${(f)"$(git branch -r 2>/dev/null | sed 's/.*origin\///' | grep -v HEAD)"})
|
|
92
|
+
fi
|
|
93
|
+
_describe -t branches 'branches' branches
|
|
94
|
+
;;
|
|
95
|
+
esac
|
|
96
|
+
;;
|
|
97
|
+
|
|
98
|
+
token)
|
|
99
|
+
_arguments \
|
|
100
|
+
'--check[Check if a token is stored]' \
|
|
101
|
+
'--store[Store a token in the system keychain]' \
|
|
102
|
+
'--reset[Delete the stored token]' \
|
|
103
|
+
$global_opts
|
|
104
|
+
;;
|
|
105
|
+
|
|
106
|
+
annotations)
|
|
107
|
+
_arguments \
|
|
108
|
+
':build reference:(org/pipeline/123)' \
|
|
109
|
+
'--context[Filter annotations by context]:context:' \
|
|
110
|
+
$global_opts
|
|
111
|
+
;;
|
|
112
|
+
|
|
113
|
+
completions)
|
|
114
|
+
if (( CURRENT == 3 )); then
|
|
115
|
+
local -a shells
|
|
116
|
+
shells=(fish bash zsh)
|
|
117
|
+
_describe -t shells 'shell type' shells
|
|
118
|
+
else
|
|
119
|
+
_arguments $global_opts
|
|
120
|
+
fi
|
|
121
|
+
;;
|
|
122
|
+
|
|
123
|
+
boom)
|
|
124
|
+
_arguments \
|
|
125
|
+
'--type[Type of error to throw]:type:(basic api object)' \
|
|
126
|
+
$global_opts
|
|
127
|
+
;;
|
|
128
|
+
|
|
129
|
+
*)
|
|
130
|
+
_arguments $global_opts
|
|
131
|
+
;;
|
|
132
|
+
esac
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# Also support bin/bktide
|
|
136
|
+
compdef _bktide bin/bktide
|
|
137
|
+
|
|
138
|
+
_bktide "$@"
|
|
139
|
+
|
|
@@ -118,7 +118,12 @@ export class BaseCommand {
|
|
|
118
118
|
if (options.token) {
|
|
119
119
|
return options.token;
|
|
120
120
|
}
|
|
121
|
-
//
|
|
121
|
+
// Prefer environment variables first under Alfred or if explicitly provided
|
|
122
|
+
const envToken = process.env.BUILDKITE_API_TOKEN || process.env.BK_TOKEN;
|
|
123
|
+
if (envToken) {
|
|
124
|
+
return envToken;
|
|
125
|
+
}
|
|
126
|
+
// Next try to get token from keyring (outside Alfred this will lazy-load)
|
|
122
127
|
try {
|
|
123
128
|
const storedToken = await this.credentialManager.getToken();
|
|
124
129
|
if (storedToken) {
|
|
@@ -129,13 +134,8 @@ export class BaseCommand {
|
|
|
129
134
|
catch (error) {
|
|
130
135
|
logger.debug('Error retrieving token from keychain', error);
|
|
131
136
|
}
|
|
132
|
-
// Finally fall back to environment variable
|
|
133
|
-
const envToken = process.env.BK_TOKEN;
|
|
134
|
-
if (envToken) {
|
|
135
|
-
return envToken;
|
|
136
|
-
}
|
|
137
137
|
if (options.requiresToken) {
|
|
138
|
-
throw new Error('API token required. Set via --token, BK_TOKEN
|
|
138
|
+
throw new Error('API token required. Set via --token, BUILDKITE_API_TOKEN/BK_TOKEN env vars, or store it using --save-token.');
|
|
139
139
|
}
|
|
140
140
|
else {
|
|
141
141
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseCommand.js","sourceRoot":"/","sources":["commands/BaseCommand.ts"],"names":[],"mappings":"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","sourcesContent":["import { BuildkiteClient } from '../services/BuildkiteClient.js';\nimport { BuildkiteRestClient, BuildkiteRestClientOptions } from '../services/BuildkiteRestClient.js';\nimport { FormatterFactory, FormatterType } from '../formatters/index.js';\nimport { logger } from '../services/logger.js';\nimport { CredentialManager } from '../services/CredentialManager.js';\n\nexport interface BaseCommandOptions {\n cacheTTL?: number;\n clearCache?: boolean;\n debug?: boolean;\n filter?: string;\n format?: string;\n noCache?: boolean;\n token?: string;\n}\n\n// Extended Error interface for API and GraphQL errors\ninterface ApiError extends Error {\n response?: {\n errors?: Array<{\n message: string;\n path?: string[];\n locations?: Array<{line: number; column: number}>;\n }>;\n };\n request?: {\n url?: string;\n method?: string;\n };\n}\n\nexport abstract class BaseCommand {\n protected token: string | undefined;\n protected requiresToken: boolean = true;\n private _client: BuildkiteClient | undefined;\n private _restClient: BuildkiteRestClient | undefined;\n private _restClientOptions: BuildkiteRestClientOptions | undefined;\n \n protected options: Partial<BaseCommandOptions>;\n protected initialized: boolean = false;\n protected static credentialManager = new CredentialManager();\n\n constructor(options?: Partial<BaseCommandOptions>) {\n this.options = options || {};\n this.token = this.options.token;\n \n if (this.options.debug) {\n // Include token length (not the actual token) for debugging auth issues\n // Debug mode is already handled here by logger.debug use\n logger.debug('BaseCommandHandler options:', {\n ...options,\n token: this.token ? `${this.token.substring(0, 4)}...${this.token.substring(this.token.length - 4)} (${this.token.length} chars)` : 'Not provided'\n });\n }\n }\n\n get client(): BuildkiteClient {\n if (this._client) {\n return this._client;\n } else {\n if (this.token) {\n this._client = new BuildkiteClient(this.token, this.options);\n return this._client;\n } else {\n throw new Error('No token provided');\n }\n }\n }\n\n get restClient(): BuildkiteRestClient {\n if (this._restClient) {\n return this._restClient;\n } else {\n if (this.token) {\n this._restClient = new BuildkiteRestClient(this.token, this.options);\n return this._restClient;\n } else {\n throw new Error('No token provided');\n }\n }\n }\n\n get restClientOptions(): BuildkiteRestClientOptions {\n if (this._restClientOptions) {\n return this._restClientOptions;\n } else {\n // Configure REST client with the same caching options\n const restClientOptions: BuildkiteRestClientOptions = {\n debug: this.options?.debug,\n caching: !this.options?.noCache,\n };\n \n // If a specific cache TTL is provided, apply it to REST client\n if (this.options?.cacheTTL) {\n restClientOptions.cacheTTLs = {\n default: this.options.cacheTTL,\n builds: this.options.cacheTTL,\n };\n }\n return restClientOptions;\n }\n }\n\n static get requiresToken(): boolean {\n return true;\n }\n \n protected async ensureInitialized(): Promise<void> {\n // No additional initialization needed\n return Promise.resolve();\n }\n\n protected handleError(error: any, debug: boolean = false): void {\n // Only log the error message and stack trace\n if (error instanceof Error) {\n logger.error(error, 'Error occurred');\n \n // If it's a GraphQL error or API error, show more details\n const apiError = error as ApiError;\n if (apiError.response?.errors) {\n apiError.response.errors.forEach((gqlError, index) => {\n logger.error({ path: gqlError.path }, `GraphQL Error ${index + 1}: ${gqlError.message}`);\n });\n }\n \n // Show request details if available and in debug mode\n if (debug && apiError.request) {\n logger.debug({ \n url: apiError.request.url,\n method: apiError.request.method \n }, 'Request Details');\n }\n } else if (typeof error === 'object') {\n logger.error({ error }, 'Unknown error occurred');\n } else {\n logger.error({ error }, 'Unknown error occurred');\n }\n \n if (debug) {\n logger.debug({ \n timestamp: new Date().toISOString(),\n nodeVersion: process.version,\n platform: `${process.platform} (${process.arch})`\n }, 'Debug Information');\n }\n }\n\n // Static helper to get token from options, keyring, or environment\n static async getToken(options: any): Promise<string | undefined> {\n // First check if token is provided directly in options\n if (options.token) {\n return options.token;\n }\n \n // Next try to get token from keyring\n try {\n const storedToken = await this.credentialManager.getToken();\n if (storedToken) {\n logger.debug('Using token from system keychain');\n return storedToken;\n }\n } catch (error) {\n logger.debug('Error retrieving token from keychain', error);\n }\n \n // Finally fall back to environment variable\n const envToken = process.env.BK_TOKEN;\n if (envToken) {\n return envToken;\n }\n \n if (options.requiresToken) {\n throw new Error('API token required. Set via --token, BK_TOKEN environment variable, or store it using --save-token.');\n } else {\n return\n }\n }\n\n /**\n * Get the appropriate formatter based on command-specific type and format option\n * @param type The formatter type ('pipeline', 'build', 'viewer')\n * @param options Command options that may include a format\n * @returns The appropriate formatter\n */\n protected getFormatter(type: FormatterType, options: BaseCommandOptions) {\n // Format precedence: command line option > constructor option > default\n const format = options.format || this.options.format || 'plain';\n if (options.debug) {\n logger.debug(`Using ${format} formatter for ${type}`);\n }\n return FormatterFactory.getFormatter(type, format);\n }\n\n /**\n * Execute the command with the given options\n * @param options Command options\n * @returns A promise that resolves to an exit code (0 for success, non-zero for errors)\n */\n abstract execute(options: BaseCommandOptions): Promise<number>;\n}"]}
|
|
1
|
+
{"version":3,"file":"BaseCommand.js","sourceRoot":"/","sources":["commands/BaseCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAA8B,MAAM,oCAAoC,CAAC;AACrG,OAAO,EAAE,gBAAgB,EAAiB,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AA6BrE,MAAM,OAAgB,WAAW;IACrB,KAAK,CAAqB;IAC1B,aAAa,GAAY,IAAI,CAAC;IAChC,OAAO,CAA8B;IACrC,WAAW,CAAkC;IAC7C,kBAAkB,CAAyC;IAEzD,OAAO,CAA8B;IACrC,WAAW,GAAY,KAAK,CAAC;IAC7B,MAAM,CAAC,iBAAiB,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAE7D,YAAY,OAAqC;QAC/C,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QAEhC,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACvB,wEAAwE;YACxE,yDAAyD;YACzD,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE;gBAC1C,GAAG,OAAO;gBACV,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,cAAc;aACnJ,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,MAAM;QACR,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC,OAAO,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC7D,OAAO,IAAI,CAAC,OAAO,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,UAAU;QACZ,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,WAAW,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrE,OAAO,IAAI,CAAC,WAAW,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,iBAAiB;QACnB,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,kBAAkB,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,sDAAsD;YACpD,MAAM,iBAAiB,GAA+B;gBACpD,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK;gBAC1B,OAAO,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO;aAChC,CAAC;YAEF,+DAA+D;YAC/D,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC;gBAC3B,iBAAiB,CAAC,SAAS,GAAG;oBAC5B,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;oBAC9B,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;iBAC9B,CAAC;YACN,CAAC;YACD,OAAO,iBAAiB,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,MAAM,KAAK,aAAa;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAES,KAAK,CAAC,iBAAiB;QAC/B,sCAAsC;QACtC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAES,WAAW,CAAC,KAAU,EAAE,QAAiB,KAAK;QACtD,6CAA6C;QAC7C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;YAEtC,0DAA0D;YAC1D,MAAM,QAAQ,GAAG,KAAiB,CAAC;YACnC,IAAI,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;gBAC9B,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE;oBACnD,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,EAAE,iBAAiB,KAAK,GAAG,CAAC,KAAK,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC3F,CAAC,CAAC,CAAC;YACL,CAAC;YAED,sDAAsD;YACtD,IAAI,KAAK,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBAC9B,MAAM,CAAC,KAAK,CAAC;oBACX,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG;oBACzB,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM;iBAChC,EAAE,iBAAiB,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,wBAAwB,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,wBAAwB,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,CAAC;gBACX,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,WAAW,EAAE,OAAO,CAAC,OAAO;gBAC5B,QAAQ,EAAE,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,IAAI,GAAG;aAClD,EAAE,mBAAmB,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAY;QAChC,uDAAuD;QACvD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC,KAAK,CAAC;QACvB,CAAC;QAED,4EAA4E;QAC5E,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;QACzE,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,0EAA0E;QAC1E,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;YAC5D,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBACjD,OAAO,WAAW,CAAC;YACrB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,6GAA6G,CAAC,CAAC;QACjI,CAAC;aAAM,CAAC;YACN,OAAM;QACR,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACO,YAAY,CAAC,IAAmB,EAAE,OAA2B;QACrE,wEAAwE;QACxE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC;QAChE,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,CAAC,KAAK,CAAC,SAAS,MAAM,kBAAkB,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,gBAAgB,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC","sourcesContent":["import { BuildkiteClient } from '../services/BuildkiteClient.js';\nimport { BuildkiteRestClient, BuildkiteRestClientOptions } from '../services/BuildkiteRestClient.js';\nimport { FormatterFactory, FormatterType } from '../formatters/index.js';\nimport { logger } from '../services/logger.js';\nimport { CredentialManager } from '../services/CredentialManager.js';\n\nexport interface BaseCommandOptions {\n cacheTTL?: number;\n clearCache?: boolean;\n debug?: boolean;\n filter?: string;\n format?: string;\n noCache?: boolean;\n quiet?: boolean;\n tips?: boolean;\n token?: string;\n}\n\n// Extended Error interface for API and GraphQL errors\ninterface ApiError extends Error {\n response?: {\n errors?: Array<{\n message: string;\n path?: string[];\n locations?: Array<{line: number; column: number}>;\n }>;\n };\n request?: {\n url?: string;\n method?: string;\n };\n}\n\nexport abstract class BaseCommand {\n protected token: string | undefined;\n protected requiresToken: boolean = true;\n private _client: BuildkiteClient | undefined;\n private _restClient: BuildkiteRestClient | undefined;\n private _restClientOptions: BuildkiteRestClientOptions | undefined;\n \n protected options: Partial<BaseCommandOptions>;\n protected initialized: boolean = false;\n protected static credentialManager = new CredentialManager();\n\n constructor(options?: Partial<BaseCommandOptions>) {\n this.options = options || {};\n this.token = this.options.token;\n \n if (this.options.debug) {\n // Include token length (not the actual token) for debugging auth issues\n // Debug mode is already handled here by logger.debug use\n logger.debug('BaseCommandHandler options:', {\n ...options,\n token: this.token ? `${this.token.substring(0, 4)}...${this.token.substring(this.token.length - 4)} (${this.token.length} chars)` : 'Not provided'\n });\n }\n }\n\n get client(): BuildkiteClient {\n if (this._client) {\n return this._client;\n } else {\n if (this.token) {\n this._client = new BuildkiteClient(this.token, this.options);\n return this._client;\n } else {\n throw new Error('No token provided');\n }\n }\n }\n\n get restClient(): BuildkiteRestClient {\n if (this._restClient) {\n return this._restClient;\n } else {\n if (this.token) {\n this._restClient = new BuildkiteRestClient(this.token, this.options);\n return this._restClient;\n } else {\n throw new Error('No token provided');\n }\n }\n }\n\n get restClientOptions(): BuildkiteRestClientOptions {\n if (this._restClientOptions) {\n return this._restClientOptions;\n } else {\n // Configure REST client with the same caching options\n const restClientOptions: BuildkiteRestClientOptions = {\n debug: this.options?.debug,\n caching: !this.options?.noCache,\n };\n \n // If a specific cache TTL is provided, apply it to REST client\n if (this.options?.cacheTTL) {\n restClientOptions.cacheTTLs = {\n default: this.options.cacheTTL,\n builds: this.options.cacheTTL,\n };\n }\n return restClientOptions;\n }\n }\n\n static get requiresToken(): boolean {\n return true;\n }\n \n protected async ensureInitialized(): Promise<void> {\n // No additional initialization needed\n return Promise.resolve();\n }\n\n protected handleError(error: any, debug: boolean = false): void {\n // Only log the error message and stack trace\n if (error instanceof Error) {\n logger.error(error, 'Error occurred');\n \n // If it's a GraphQL error or API error, show more details\n const apiError = error as ApiError;\n if (apiError.response?.errors) {\n apiError.response.errors.forEach((gqlError, index) => {\n logger.error({ path: gqlError.path }, `GraphQL Error ${index + 1}: ${gqlError.message}`);\n });\n }\n \n // Show request details if available and in debug mode\n if (debug && apiError.request) {\n logger.debug({ \n url: apiError.request.url,\n method: apiError.request.method \n }, 'Request Details');\n }\n } else if (typeof error === 'object') {\n logger.error({ error }, 'Unknown error occurred');\n } else {\n logger.error({ error }, 'Unknown error occurred');\n }\n \n if (debug) {\n logger.debug({ \n timestamp: new Date().toISOString(),\n nodeVersion: process.version,\n platform: `${process.platform} (${process.arch})`\n }, 'Debug Information');\n }\n }\n\n // Static helper to get token from options, keyring, or environment\n static async getToken(options: any): Promise<string | undefined> {\n // First check if token is provided directly in options\n if (options.token) {\n return options.token;\n }\n \n // Prefer environment variables first under Alfred or if explicitly provided\n const envToken = process.env.BUILDKITE_API_TOKEN || process.env.BK_TOKEN;\n if (envToken) {\n return envToken;\n }\n \n // Next try to get token from keyring (outside Alfred this will lazy-load)\n try {\n const storedToken = await this.credentialManager.getToken();\n if (storedToken) {\n logger.debug('Using token from system keychain');\n return storedToken;\n }\n } catch (error) {\n logger.debug('Error retrieving token from keychain', error);\n }\n \n if (options.requiresToken) {\n throw new Error('API token required. Set via --token, BUILDKITE_API_TOKEN/BK_TOKEN env vars, or store it using --save-token.');\n } else {\n return\n }\n }\n\n /**\n * Get the appropriate formatter based on command-specific type and format option\n * @param type The formatter type ('pipeline', 'build', 'viewer')\n * @param options Command options that may include a format\n * @returns The appropriate formatter\n */\n protected getFormatter(type: FormatterType, options: BaseCommandOptions) {\n // Format precedence: command line option > constructor option > default\n const format = options.format || this.options.format || 'plain';\n if (options.debug) {\n logger.debug(`Using ${format} formatter for ${type}`);\n }\n return FormatterFactory.getFormatter(type, format);\n }\n\n /**\n * Execute the command with the given options\n * @param options Command options\n * @returns A promise that resolves to an exit code (0 for success, non-zero for errors)\n */\n abstract execute(options: BaseCommandOptions): Promise<number>;\n}"]}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { BaseCommand } from './BaseCommand.js';
|
|
5
|
+
import { logger } from '../services/logger.js';
|
|
6
|
+
export class GenerateCompletions extends BaseCommand {
|
|
7
|
+
static requiresToken = false;
|
|
8
|
+
async execute(options) {
|
|
9
|
+
const shell = options.shell || this.detectShell();
|
|
10
|
+
if (!shell) {
|
|
11
|
+
logger.error('Could not detect shell. Please specify with: bktide completions <shell>');
|
|
12
|
+
logger.info('Supported shells: fish, bash, zsh');
|
|
13
|
+
return 1;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const completionScript = await this.getCompletionScript(shell);
|
|
17
|
+
if (completionScript) {
|
|
18
|
+
// Output the completion script to stdout
|
|
19
|
+
console.log(completionScript);
|
|
20
|
+
if (!options.quiet && process.stderr.isTTY) {
|
|
21
|
+
// Show installation instructions on stderr
|
|
22
|
+
this.showInstallInstructions(shell);
|
|
23
|
+
}
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
logger.error(`No completion script available for shell: ${shell}`);
|
|
28
|
+
logger.info('Supported shells: fish, bash, zsh');
|
|
29
|
+
return 1;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
this.handleError(error, options.debug);
|
|
34
|
+
return 1;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
detectShell() {
|
|
38
|
+
// Try to detect the current shell
|
|
39
|
+
const shellEnv = process.env.SHELL;
|
|
40
|
+
if (shellEnv) {
|
|
41
|
+
const shellName = path.basename(shellEnv);
|
|
42
|
+
if (['fish', 'bash', 'zsh'].includes(shellName)) {
|
|
43
|
+
return shellName;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
async getCompletionScript(shell) {
|
|
49
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
50
|
+
const __dirname = path.dirname(__filename);
|
|
51
|
+
// Look for completion scripts in the completions directory
|
|
52
|
+
const completionsDir = path.resolve(__dirname, '../../completions');
|
|
53
|
+
let scriptFile;
|
|
54
|
+
switch (shell) {
|
|
55
|
+
case 'fish':
|
|
56
|
+
// Use the dynamic version if jq is available, otherwise static
|
|
57
|
+
if (await this.isCommandAvailable('jq')) {
|
|
58
|
+
scriptFile = path.join(completionsDir, 'bktide-dynamic.fish');
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
scriptFile = path.join(completionsDir, 'bktide.fish');
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
64
|
+
case 'bash':
|
|
65
|
+
scriptFile = path.join(completionsDir, 'bktide.bash');
|
|
66
|
+
break;
|
|
67
|
+
case 'zsh':
|
|
68
|
+
scriptFile = path.join(completionsDir, 'bktide.zsh');
|
|
69
|
+
break;
|
|
70
|
+
default:
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
// Check if the completion script exists
|
|
74
|
+
if (fs.existsSync(scriptFile)) {
|
|
75
|
+
return fs.readFileSync(scriptFile, 'utf-8');
|
|
76
|
+
}
|
|
77
|
+
// Fallback: Generate basic completion based on shell type
|
|
78
|
+
return this.generateBasicCompletion(shell);
|
|
79
|
+
}
|
|
80
|
+
async isCommandAvailable(command) {
|
|
81
|
+
try {
|
|
82
|
+
const { exec } = await import('child_process');
|
|
83
|
+
return new Promise((resolve) => {
|
|
84
|
+
exec(`which ${command}`, (error) => {
|
|
85
|
+
resolve(!error);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
generateBasicCompletion(shell) {
|
|
94
|
+
// Basic completion generation for shells
|
|
95
|
+
const commands = ['viewer', 'orgs', 'pipelines', 'builds', 'token', 'annotations', 'completions', 'boom'];
|
|
96
|
+
const globalOptions = [
|
|
97
|
+
'--log-level', '--debug', '--no-cache', '--cache-ttl', '--clear-cache',
|
|
98
|
+
'--token', '--save-token', '--format', '--color', '--quiet', '--tips',
|
|
99
|
+
'--no-tips', '--ascii', '--help', '--version'
|
|
100
|
+
];
|
|
101
|
+
switch (shell) {
|
|
102
|
+
case 'fish':
|
|
103
|
+
return this.generateFishCompletion(commands, globalOptions);
|
|
104
|
+
case 'bash':
|
|
105
|
+
return this.generateBashCompletion(commands, globalOptions);
|
|
106
|
+
case 'zsh':
|
|
107
|
+
return this.generateZshCompletion(commands, globalOptions);
|
|
108
|
+
default:
|
|
109
|
+
return '';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
generateFishCompletion(commands, options) {
|
|
113
|
+
let script = '# Fish completions for bktide\n';
|
|
114
|
+
script += '# Generated by bktide completions fish\n\n';
|
|
115
|
+
script += '# Disable file completions\n';
|
|
116
|
+
script += 'complete -c bktide -f\n';
|
|
117
|
+
script += 'complete -c bin/bktide -f\n\n';
|
|
118
|
+
script += '# Commands\n';
|
|
119
|
+
for (const cmd of commands) {
|
|
120
|
+
script += `complete -c bktide -n __fish_use_subcommand -a ${cmd}\n`;
|
|
121
|
+
script += `complete -c bin/bktide -n __fish_use_subcommand -a ${cmd}\n`;
|
|
122
|
+
}
|
|
123
|
+
script += '\n# Global options\n';
|
|
124
|
+
for (const opt of options) {
|
|
125
|
+
const shortOpt = this.getShortOption(opt);
|
|
126
|
+
if (shortOpt) {
|
|
127
|
+
script += `complete -c bktide -s ${shortOpt} -l ${opt.replace('--', '')}\n`;
|
|
128
|
+
script += `complete -c bin/bktide -s ${shortOpt} -l ${opt.replace('--', '')}\n`;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
script += `complete -c bktide -l ${opt.replace('--', '')}\n`;
|
|
132
|
+
script += `complete -c bin/bktide -l ${opt.replace('--', '')}\n`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return script;
|
|
136
|
+
}
|
|
137
|
+
generateBashCompletion(commands, options) {
|
|
138
|
+
let script = '#!/bin/bash\n';
|
|
139
|
+
script += '# Bash completions for bktide\n';
|
|
140
|
+
script += '# Generated by bktide completions bash\n\n';
|
|
141
|
+
script += '_bktide() {\n';
|
|
142
|
+
script += ' local cur prev commands options\n';
|
|
143
|
+
script += ' COMPREPLY=()\n';
|
|
144
|
+
script += ' cur="${COMP_WORDS[COMP_CWORD]}"\n';
|
|
145
|
+
script += ' prev="${COMP_WORDS[COMP_CWORD-1]}"\n';
|
|
146
|
+
script += ` commands="${commands.join(' ')}"\n`;
|
|
147
|
+
script += ` options="${options.join(' ')}"\n\n`;
|
|
148
|
+
script += ' if [[ ${COMP_CWORD} -eq 1 ]]; then\n';
|
|
149
|
+
script += ' COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )\n';
|
|
150
|
+
script += ' else\n';
|
|
151
|
+
script += ' COMPREPLY=( $(compgen -W "${options}" -- ${cur}) )\n';
|
|
152
|
+
script += ' fi\n';
|
|
153
|
+
script += ' return 0\n';
|
|
154
|
+
script += '}\n\n';
|
|
155
|
+
script += 'complete -F _bktide bktide\n';
|
|
156
|
+
script += 'complete -F _bktide bin/bktide\n';
|
|
157
|
+
return script;
|
|
158
|
+
}
|
|
159
|
+
generateZshCompletion(commands, options) {
|
|
160
|
+
let script = '#compdef bktide\n';
|
|
161
|
+
script += '# Zsh completions for bktide\n';
|
|
162
|
+
script += '# Generated by bktide completions zsh\n\n';
|
|
163
|
+
script += '_bktide() {\n';
|
|
164
|
+
script += ' local -a commands options\n';
|
|
165
|
+
script += ` commands=(${commands.map(c => `'${c}'`).join(' ')})\n`;
|
|
166
|
+
script += ` options=(${options.map(o => `'${o}'`).join(' ')})\n\n`;
|
|
167
|
+
script += ' if (( CURRENT == 2 )); then\n';
|
|
168
|
+
script += ' _describe -t commands "bktide commands" commands\n';
|
|
169
|
+
script += ' else\n';
|
|
170
|
+
script += ' _describe -t options "bktide options" options\n';
|
|
171
|
+
script += ' fi\n';
|
|
172
|
+
script += '}\n\n';
|
|
173
|
+
script += '_bktide "$@"\n';
|
|
174
|
+
return script;
|
|
175
|
+
}
|
|
176
|
+
getShortOption(longOption) {
|
|
177
|
+
const shortMap = {
|
|
178
|
+
'--debug': 'd',
|
|
179
|
+
'--token': 't',
|
|
180
|
+
'--format': 'f',
|
|
181
|
+
'--quiet': 'q',
|
|
182
|
+
'--help': 'h',
|
|
183
|
+
'--version': 'V',
|
|
184
|
+
};
|
|
185
|
+
return shortMap[longOption];
|
|
186
|
+
}
|
|
187
|
+
showInstallInstructions(shell) {
|
|
188
|
+
// Use console.error to ensure instructions go to stderr, not stdout
|
|
189
|
+
console.error('\n');
|
|
190
|
+
console.error(`To install ${shell} completions:`);
|
|
191
|
+
switch (shell) {
|
|
192
|
+
case 'fish':
|
|
193
|
+
console.error(' Option 1 (User-specific):');
|
|
194
|
+
console.error(' bktide completions fish > ~/.config/fish/completions/bktide.fish');
|
|
195
|
+
console.error('');
|
|
196
|
+
console.error(' Option 2 (System-wide - requires sudo):');
|
|
197
|
+
console.error(' bktide completions fish | sudo tee /usr/share/fish/vendor_completions.d/bktide.fish');
|
|
198
|
+
console.error('');
|
|
199
|
+
console.error(' For local development with bin/bktide:');
|
|
200
|
+
console.error(' The completions will work for both "bktide" and "bin/bktide" automatically');
|
|
201
|
+
break;
|
|
202
|
+
case 'bash':
|
|
203
|
+
console.error(' Option 1 (User-specific - add to ~/.bashrc):');
|
|
204
|
+
console.error(' source <(bktide completions bash)');
|
|
205
|
+
console.error('');
|
|
206
|
+
console.error(' Option 2 (System-wide - requires sudo):');
|
|
207
|
+
console.error(' bktide completions bash | sudo tee /etc/bash_completion.d/bktide');
|
|
208
|
+
console.error('');
|
|
209
|
+
console.error(' For macOS with Homebrew bash-completion:');
|
|
210
|
+
console.error(' bktide completions bash > $(brew --prefix)/etc/bash_completion.d/bktide');
|
|
211
|
+
break;
|
|
212
|
+
case 'zsh':
|
|
213
|
+
console.error(' Option 1 (User-specific - add to ~/.zshrc):');
|
|
214
|
+
console.error(' source <(bktide completions zsh)');
|
|
215
|
+
console.error('');
|
|
216
|
+
console.error(' Option 2 (Add to fpath - add to ~/.zshrc):');
|
|
217
|
+
console.error(' mkdir -p ~/.zsh/completions');
|
|
218
|
+
console.error(' bktide completions zsh > ~/.zsh/completions/_bktide');
|
|
219
|
+
console.error(' echo "fpath=(~/.zsh/completions $fpath)" >> ~/.zshrc');
|
|
220
|
+
console.error(' echo "autoload -U compinit && compinit" >> ~/.zshrc');
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
console.error('');
|
|
224
|
+
console.error('After installation, restart your shell or run:');
|
|
225
|
+
switch (shell) {
|
|
226
|
+
case 'fish':
|
|
227
|
+
console.error(' source ~/.config/fish/config.fish');
|
|
228
|
+
break;
|
|
229
|
+
case 'bash':
|
|
230
|
+
console.error(' source ~/.bashrc');
|
|
231
|
+
break;
|
|
232
|
+
case 'zsh':
|
|
233
|
+
console.error(' source ~/.zshrc');
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=GenerateCompletions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GenerateCompletions.js","sourceRoot":"/","sources":["commands/GenerateCompletions.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { BaseCommand, BaseCommandOptions } from './BaseCommand.js';\nimport { logger } from '../services/logger.js';\n\nexport interface GenerateCompletionsOptions extends BaseCommandOptions {\n shell?: string;\n}\n\nexport class GenerateCompletions extends BaseCommand {\n static requiresToken = false;\n\n async execute(options: GenerateCompletionsOptions): Promise<number> {\n const shell = options.shell || this.detectShell();\n \n if (!shell) {\n logger.error('Could not detect shell. Please specify with: bktide completions <shell>');\n logger.info('Supported shells: fish, bash, zsh');\n return 1;\n }\n\n try {\n const completionScript = await this.getCompletionScript(shell);\n \n if (completionScript) {\n // Output the completion script to stdout\n console.log(completionScript);\n \n if (!options.quiet && process.stderr.isTTY) {\n // Show installation instructions on stderr\n this.showInstallInstructions(shell);\n }\n \n return 0;\n } else {\n logger.error(`No completion script available for shell: ${shell}`);\n logger.info('Supported shells: fish, bash, zsh');\n return 1;\n }\n } catch (error) {\n this.handleError(error, options.debug);\n return 1;\n }\n }\n\n private detectShell(): string | undefined {\n // Try to detect the current shell\n const shellEnv = process.env.SHELL;\n if (shellEnv) {\n const shellName = path.basename(shellEnv);\n if (['fish', 'bash', 'zsh'].includes(shellName)) {\n return shellName;\n }\n }\n return undefined;\n }\n\n private async getCompletionScript(shell: string): Promise<string | undefined> {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n \n // Look for completion scripts in the completions directory\n const completionsDir = path.resolve(__dirname, '../../completions');\n \n let scriptFile: string;\n switch (shell) {\n case 'fish':\n // Use the dynamic version if jq is available, otherwise static\n if (await this.isCommandAvailable('jq')) {\n scriptFile = path.join(completionsDir, 'bktide-dynamic.fish');\n } else {\n scriptFile = path.join(completionsDir, 'bktide.fish');\n }\n break;\n case 'bash':\n scriptFile = path.join(completionsDir, 'bktide.bash');\n break;\n case 'zsh':\n scriptFile = path.join(completionsDir, 'bktide.zsh');\n break;\n default:\n return undefined;\n }\n\n // Check if the completion script exists\n if (fs.existsSync(scriptFile)) {\n return fs.readFileSync(scriptFile, 'utf-8');\n }\n\n // Fallback: Generate basic completion based on shell type\n return this.generateBasicCompletion(shell);\n }\n\n private async isCommandAvailable(command: string): Promise<boolean> {\n try {\n const { exec } = await import('child_process');\n return new Promise((resolve) => {\n exec(`which ${command}`, (error) => {\n resolve(!error);\n });\n });\n } catch {\n return false;\n }\n }\n\n private generateBasicCompletion(shell: string): string {\n // Basic completion generation for shells\n const commands = ['viewer', 'orgs', 'pipelines', 'builds', 'token', 'annotations', 'completions', 'boom'];\n const globalOptions = [\n '--log-level', '--debug', '--no-cache', '--cache-ttl', '--clear-cache',\n '--token', '--save-token', '--format', '--color', '--quiet', '--tips',\n '--no-tips', '--ascii', '--help', '--version'\n ];\n\n switch (shell) {\n case 'fish':\n return this.generateFishCompletion(commands, globalOptions);\n case 'bash':\n return this.generateBashCompletion(commands, globalOptions);\n case 'zsh':\n return this.generateZshCompletion(commands, globalOptions);\n default:\n return '';\n }\n }\n\n private generateFishCompletion(commands: string[], options: string[]): string {\n let script = '# Fish completions for bktide\\n';\n script += '# Generated by bktide completions fish\\n\\n';\n script += '# Disable file completions\\n';\n script += 'complete -c bktide -f\\n';\n script += 'complete -c bin/bktide -f\\n\\n';\n \n script += '# Commands\\n';\n for (const cmd of commands) {\n script += `complete -c bktide -n __fish_use_subcommand -a ${cmd}\\n`;\n script += `complete -c bin/bktide -n __fish_use_subcommand -a ${cmd}\\n`;\n }\n \n script += '\\n# Global options\\n';\n for (const opt of options) {\n const shortOpt = this.getShortOption(opt);\n if (shortOpt) {\n script += `complete -c bktide -s ${shortOpt} -l ${opt.replace('--', '')}\\n`;\n script += `complete -c bin/bktide -s ${shortOpt} -l ${opt.replace('--', '')}\\n`;\n } else {\n script += `complete -c bktide -l ${opt.replace('--', '')}\\n`;\n script += `complete -c bin/bktide -l ${opt.replace('--', '')}\\n`;\n }\n }\n \n return script;\n }\n\n private generateBashCompletion(commands: string[], options: string[]): string {\n let script = '#!/bin/bash\\n';\n script += '# Bash completions for bktide\\n';\n script += '# Generated by bktide completions bash\\n\\n';\n \n script += '_bktide() {\\n';\n script += ' local cur prev commands options\\n';\n script += ' COMPREPLY=()\\n';\n script += ' cur=\"${COMP_WORDS[COMP_CWORD]}\"\\n';\n script += ' prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\\n';\n script += ` commands=\"${commands.join(' ')}\"\\n`;\n script += ` options=\"${options.join(' ')}\"\\n\\n`;\n \n script += ' if [[ ${COMP_CWORD} -eq 1 ]]; then\\n';\n script += ' COMPREPLY=( $(compgen -W \"${commands}\" -- ${cur}) )\\n';\n script += ' else\\n';\n script += ' COMPREPLY=( $(compgen -W \"${options}\" -- ${cur}) )\\n';\n script += ' fi\\n';\n script += ' return 0\\n';\n script += '}\\n\\n';\n \n script += 'complete -F _bktide bktide\\n';\n script += 'complete -F _bktide bin/bktide\\n';\n \n return script;\n }\n\n private generateZshCompletion(commands: string[], options: string[]): string {\n let script = '#compdef bktide\\n';\n script += '# Zsh completions for bktide\\n';\n script += '# Generated by bktide completions zsh\\n\\n';\n \n script += '_bktide() {\\n';\n script += ' local -a commands options\\n';\n script += ` commands=(${commands.map(c => `'${c}'`).join(' ')})\\n`;\n script += ` options=(${options.map(o => `'${o}'`).join(' ')})\\n\\n`;\n \n script += ' if (( CURRENT == 2 )); then\\n';\n script += ' _describe -t commands \"bktide commands\" commands\\n';\n script += ' else\\n';\n script += ' _describe -t options \"bktide options\" options\\n';\n script += ' fi\\n';\n script += '}\\n\\n';\n \n script += '_bktide \"$@\"\\n';\n \n return script;\n }\n\n private getShortOption(longOption: string): string | undefined {\n const shortMap: Record<string, string> = {\n '--debug': 'd',\n '--token': 't',\n '--format': 'f',\n '--quiet': 'q',\n '--help': 'h',\n '--version': 'V',\n };\n return shortMap[longOption];\n }\n\n private showInstallInstructions(shell: string): void {\n // Use console.error to ensure instructions go to stderr, not stdout\n console.error('\\n');\n console.error(`To install ${shell} completions:`);\n \n switch (shell) {\n case 'fish':\n console.error(' Option 1 (User-specific):');\n console.error(' bktide completions fish > ~/.config/fish/completions/bktide.fish');\n console.error('');\n console.error(' Option 2 (System-wide - requires sudo):');\n console.error(' bktide completions fish | sudo tee /usr/share/fish/vendor_completions.d/bktide.fish');\n console.error('');\n console.error(' For local development with bin/bktide:');\n console.error(' The completions will work for both \"bktide\" and \"bin/bktide\" automatically');\n break;\n \n case 'bash':\n console.error(' Option 1 (User-specific - add to ~/.bashrc):');\n console.error(' source <(bktide completions bash)');\n console.error('');\n console.error(' Option 2 (System-wide - requires sudo):');\n console.error(' bktide completions bash | sudo tee /etc/bash_completion.d/bktide');\n console.error('');\n console.error(' For macOS with Homebrew bash-completion:');\n console.error(' bktide completions bash > $(brew --prefix)/etc/bash_completion.d/bktide');\n break;\n \n case 'zsh':\n console.error(' Option 1 (User-specific - add to ~/.zshrc):');\n console.error(' source <(bktide completions zsh)');\n console.error('');\n console.error(' Option 2 (Add to fpath - add to ~/.zshrc):');\n console.error(' mkdir -p ~/.zsh/completions');\n console.error(' bktide completions zsh > ~/.zsh/completions/_bktide');\n console.error(' echo \"fpath=(~/.zsh/completions $fpath)\" >> ~/.zshrc');\n console.error(' echo \"autoload -U compinit && compinit\" >> ~/.zshrc');\n break;\n }\n \n console.error('');\n console.error('After installation, restart your shell or run:');\n switch (shell) {\n case 'fish':\n console.error(' source ~/.config/fish/config.fish');\n break;\n case 'bash':\n console.error(' source ~/.bashrc');\n break;\n case 'zsh':\n console.error(' source ~/.zshrc');\n break;\n }\n }\n}\n"]}
|
|
@@ -2,6 +2,7 @@ import { BaseCommand } from './BaseCommand.js';
|
|
|
2
2
|
import { logger } from '../services/logger.js';
|
|
3
3
|
import { parseBuildRef } from '../utils/parseBuildRef.js';
|
|
4
4
|
import { FormatterFactory, FormatterType } from '../formatters/index.js';
|
|
5
|
+
import { Progress } from '../ui/progress.js';
|
|
5
6
|
export class ListAnnotations extends BaseCommand {
|
|
6
7
|
static requiresToken = true;
|
|
7
8
|
async execute(options) {
|
|
@@ -12,6 +13,9 @@ export class ListAnnotations extends BaseCommand {
|
|
|
12
13
|
logger.error('Build reference is required');
|
|
13
14
|
return 1;
|
|
14
15
|
}
|
|
16
|
+
// Initialize reporter and spinner early
|
|
17
|
+
const format = options.format || 'plain';
|
|
18
|
+
const spinner = Progress.spinner('Fetching annotations…', { format });
|
|
15
19
|
try {
|
|
16
20
|
// Ensure the command is initialized
|
|
17
21
|
await this.ensureInitialized();
|
|
@@ -22,6 +26,7 @@ export class ListAnnotations extends BaseCommand {
|
|
|
22
26
|
// Fetch annotations from the GraphQL API
|
|
23
27
|
const buildSlug = `${buildRef.org}/${buildRef.pipeline}/${buildRef.number}`;
|
|
24
28
|
const result = await this.client.getBuildAnnotations(buildSlug);
|
|
29
|
+
spinner.stop();
|
|
25
30
|
// Extract annotations from the GraphQL response
|
|
26
31
|
let annotations = result.build?.annotations?.edges?.map((edge) => edge.node) || [];
|
|
27
32
|
// Filter by context if specified
|
|
@@ -40,9 +45,11 @@ export class ListAnnotations extends BaseCommand {
|
|
|
40
45
|
contextFilter: options.context
|
|
41
46
|
});
|
|
42
47
|
logger.console(output);
|
|
48
|
+
// Success is implicit - data display confirms retrieval
|
|
43
49
|
return 0;
|
|
44
50
|
}
|
|
45
51
|
catch (error) {
|
|
52
|
+
spinner.stop();
|
|
46
53
|
logger.error('Failed to fetch annotations:', error);
|
|
47
54
|
// Handle the error with the formatter
|
|
48
55
|
const formatter = FormatterFactory.getFormatter(FormatterType.ANNOTATION, options.format || 'plain'); // Cast to any since FormatterFactory returns BaseFormatter
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListAnnotations.js","sourceRoot":"/","sources":["commands/ListAnnotations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGzE,MAAM,OAAO,eAAgB,SAAQ,WAAW;IAC9C,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC;IAE5B,KAAK,CAAC,OAAO,CAAC,OAAY;QACxB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC7D,CAAC;QAGD,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACtB,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YAC5C,OAAO,CAAC,CAAC;QACX,CAAC;QAED,IAAI,CAAC;YACH,oCAAoC;YACpC,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAE/B,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACjD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,QAAQ,CAAC,CAAC;YACpD,CAAC;YAED,yCAAyC;YACzC,MAAM,SAAS,GAAG,GAAG,QAAQ,CAAC,GAAG,IAAI,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC5E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ListAnnotations.js","sourceRoot":"/","sources":["commands/ListAnnotations.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseCommand } from './BaseCommand.js';\nimport { logger } from '../services/logger.js';\nimport { parseBuildRef } from '../utils/parseBuildRef.js';\nimport { FormatterFactory, FormatterType } from '../formatters/index.js';\nimport { Annotation } from '../types/index.js';\n\nimport { Progress } from '../ui/progress.js';\n\nexport class ListAnnotations extends BaseCommand {\n static requiresToken = true;\n\n async execute(options: any): Promise<number> {\n if (options.debug) {\n logger.debug('Starting ListAnnotations command execution');\n }\n \n \n if (!options.buildArg) {\n logger.error('Build reference is required');\n return 1;\n }\n \n // Initialize reporter and spinner early\n const format = options.format || 'plain';\n const spinner = Progress.spinner('Fetching annotations…', { format });\n \n try {\n // Ensure the command is initialized\n await this.ensureInitialized();\n \n const buildRef = parseBuildRef(options.buildArg);\n if (options.debug) {\n logger.debug('Parsed build reference:', buildRef);\n }\n \n // Fetch annotations from the GraphQL API\n const buildSlug = `${buildRef.org}/${buildRef.pipeline}/${buildRef.number}`;\n const result = await this.client.getBuildAnnotations(buildSlug);\n spinner.stop();\n \n // Extract annotations from the GraphQL response\n let annotations: Annotation[] = result.build?.annotations?.edges?.map((edge: any) => edge.node) || [];\n \n // Filter by context if specified\n if (options.context) {\n const contextFilter = options.context.toLowerCase();\n annotations = annotations.filter(annotation => \n annotation.context.toLowerCase() === contextFilter\n );\n \n if (options.debug) {\n logger.debug(`Filtered annotations by context '${options.context}': ${annotations.length} found`);\n }\n }\n \n // Get the appropriate formatter\n const formatter = FormatterFactory.getFormatter(\n FormatterType.ANNOTATION,\n options.format || 'plain'\n ) as any; // Cast to any since FormatterFactory returns BaseFormatter\n \n // Format and output the results\n const output = formatter.formatAnnotations(annotations, {\n debug: options.debug,\n contextFilter: options.context\n });\n \n logger.console(output);\n // Success is implicit - data display confirms retrieval\n \n return 0;\n } catch (error) {\n spinner.stop();\n logger.error('Failed to fetch annotations:', error);\n \n // Handle the error with the formatter\n const formatter = FormatterFactory.getFormatter(\n FormatterType.ANNOTATION,\n options.format || 'plain'\n ) as any; // Cast to any since FormatterFactory returns BaseFormatter\n \n const errorOutput = formatter.formatAnnotations([], {\n hasError: true,\n errorMessage: error instanceof Error ? error.message : 'Unknown error occurred',\n errorType: 'api',\n debug: options.debug\n });\n \n logger.console(errorOutput);\n return 1;\n }\n }\n}\n"]}
|