berget 0.1.0 → 1.1.0
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 +92 -0
- package/dist/index.js +7 -439
- package/dist/src/client.js +193 -102
- package/dist/src/commands/api-keys.js +271 -0
- package/dist/src/commands/auth.js +65 -0
- package/dist/src/commands/autocomplete.js +24 -0
- package/dist/src/commands/billing.js +53 -0
- package/dist/src/commands/chat.js +276 -0
- package/dist/src/commands/clusters.js +69 -0
- package/dist/src/commands/index.js +25 -0
- package/dist/src/commands/models.js +69 -0
- package/dist/src/commands/users.js +43 -0
- package/dist/src/constants/command-structure.js +164 -0
- package/dist/src/services/api-key-service.js +34 -5
- package/dist/src/services/auth-service.js +83 -43
- package/dist/src/services/chat-service.js +177 -0
- package/dist/src/services/cluster-service.js +37 -2
- package/dist/src/services/collaborator-service.js +21 -4
- package/dist/src/services/flux-service.js +21 -4
- package/dist/src/services/helm-service.js +20 -3
- package/dist/src/services/kubectl-service.js +26 -5
- package/dist/src/utils/config-checker.js +50 -0
- package/dist/src/utils/default-api-key.js +111 -0
- package/dist/src/utils/token-manager.js +165 -0
- package/index.ts +5 -529
- package/package.json +6 -1
- package/src/client.ts +262 -80
- package/src/commands/api-keys.ts +364 -0
- package/src/commands/auth.ts +58 -0
- package/src/commands/autocomplete.ts +19 -0
- package/src/commands/billing.ts +41 -0
- package/src/commands/chat.ts +345 -0
- package/src/commands/clusters.ts +65 -0
- package/src/commands/index.ts +23 -0
- package/src/commands/models.ts +63 -0
- package/src/commands/users.ts +37 -0
- package/src/constants/command-structure.ts +184 -0
- package/src/services/api-key-service.ts +36 -5
- package/src/services/auth-service.ts +101 -44
- package/src/services/chat-service.ts +177 -0
- package/src/services/cluster-service.ts +37 -2
- package/src/services/collaborator-service.ts +23 -4
- package/src/services/flux-service.ts +23 -4
- package/src/services/helm-service.ts +22 -3
- package/src/services/kubectl-service.ts +28 -5
- package/src/types/api.d.ts +58 -192
- package/src/utils/config-checker.ts +23 -0
- package/src/utils/default-api-key.ts +94 -0
- package/src/utils/token-manager.ts +150 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as fs from 'fs'
|
|
2
|
+
import * as path from 'path'
|
|
3
|
+
import * as os from 'os'
|
|
4
|
+
import chalk from 'chalk'
|
|
5
|
+
|
|
6
|
+
interface DefaultApiKeyData {
|
|
7
|
+
id: string
|
|
8
|
+
name: string
|
|
9
|
+
prefix: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Manages the default API key for chat commands
|
|
14
|
+
*/
|
|
15
|
+
export class DefaultApiKeyManager {
|
|
16
|
+
private static instance: DefaultApiKeyManager
|
|
17
|
+
private configFilePath: string
|
|
18
|
+
private defaultApiKey: DefaultApiKeyData | null = null
|
|
19
|
+
|
|
20
|
+
private constructor() {
|
|
21
|
+
// Set up config file path in user's home directory
|
|
22
|
+
const bergetDir = path.join(os.homedir(), '.berget')
|
|
23
|
+
if (!fs.existsSync(bergetDir)) {
|
|
24
|
+
fs.mkdirSync(bergetDir, { recursive: true })
|
|
25
|
+
}
|
|
26
|
+
this.configFilePath = path.join(bergetDir, 'default-api-key.json')
|
|
27
|
+
this.loadConfig()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public static getInstance(): DefaultApiKeyManager {
|
|
31
|
+
if (!DefaultApiKeyManager.instance) {
|
|
32
|
+
DefaultApiKeyManager.instance = new DefaultApiKeyManager()
|
|
33
|
+
}
|
|
34
|
+
return DefaultApiKeyManager.instance
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Load default API key from file
|
|
39
|
+
*/
|
|
40
|
+
private loadConfig(): void {
|
|
41
|
+
try {
|
|
42
|
+
if (fs.existsSync(this.configFilePath)) {
|
|
43
|
+
const data = fs.readFileSync(this.configFilePath, 'utf8')
|
|
44
|
+
this.defaultApiKey = JSON.parse(data)
|
|
45
|
+
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error(chalk.dim('Failed to load default API key configuration'))
|
|
48
|
+
this.defaultApiKey = null
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Save default API key to file
|
|
54
|
+
*/
|
|
55
|
+
private saveConfig(): void {
|
|
56
|
+
try {
|
|
57
|
+
if (this.defaultApiKey) {
|
|
58
|
+
fs.writeFileSync(this.configFilePath, JSON.stringify(this.defaultApiKey, null, 2))
|
|
59
|
+
// Set file permissions to be readable only by the owner
|
|
60
|
+
fs.chmodSync(this.configFilePath, 0o600)
|
|
61
|
+
} else {
|
|
62
|
+
// If default API key is null, remove the file
|
|
63
|
+
if (fs.existsSync(this.configFilePath)) {
|
|
64
|
+
fs.unlinkSync(this.configFilePath)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(chalk.dim('Failed to save default API key configuration'))
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Set the default API key
|
|
74
|
+
*/
|
|
75
|
+
public setDefaultApiKey(id: string, name: string, prefix: string): void {
|
|
76
|
+
this.defaultApiKey = { id, name, prefix }
|
|
77
|
+
this.saveConfig()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get the default API key
|
|
82
|
+
*/
|
|
83
|
+
public getDefaultApiKey(): DefaultApiKeyData | null {
|
|
84
|
+
return this.defaultApiKey
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Clear the default API key
|
|
89
|
+
*/
|
|
90
|
+
public clearDefaultApiKey(): void {
|
|
91
|
+
this.defaultApiKey = null
|
|
92
|
+
this.saveConfig()
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import * as fs from 'fs'
|
|
2
|
+
import * as path from 'path'
|
|
3
|
+
import * as os from 'os'
|
|
4
|
+
import chalk from 'chalk'
|
|
5
|
+
|
|
6
|
+
interface TokenData {
|
|
7
|
+
access_token: string
|
|
8
|
+
refresh_token: string
|
|
9
|
+
expires_at: number // timestamp in milliseconds
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Manages authentication tokens including refresh functionality
|
|
14
|
+
*/
|
|
15
|
+
export class TokenManager {
|
|
16
|
+
private static instance: TokenManager
|
|
17
|
+
private tokenFilePath: string
|
|
18
|
+
private tokenData: TokenData | null = null
|
|
19
|
+
|
|
20
|
+
private constructor() {
|
|
21
|
+
// Set up token file path in user's home directory
|
|
22
|
+
const bergetDir = path.join(os.homedir(), '.berget')
|
|
23
|
+
if (!fs.existsSync(bergetDir)) {
|
|
24
|
+
fs.mkdirSync(bergetDir, { recursive: true })
|
|
25
|
+
}
|
|
26
|
+
this.tokenFilePath = path.join(bergetDir, 'auth.json')
|
|
27
|
+
this.loadToken()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public static getInstance(): TokenManager {
|
|
31
|
+
if (!TokenManager.instance) {
|
|
32
|
+
TokenManager.instance = new TokenManager()
|
|
33
|
+
}
|
|
34
|
+
return TokenManager.instance
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Load token data from file
|
|
39
|
+
*/
|
|
40
|
+
private loadToken(): void {
|
|
41
|
+
try {
|
|
42
|
+
if (fs.existsSync(this.tokenFilePath)) {
|
|
43
|
+
const data = fs.readFileSync(this.tokenFilePath, 'utf8')
|
|
44
|
+
this.tokenData = JSON.parse(data)
|
|
45
|
+
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error(chalk.dim('Failed to load authentication token'))
|
|
48
|
+
this.tokenData = null
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Save token data to file
|
|
54
|
+
*/
|
|
55
|
+
private saveToken(): void {
|
|
56
|
+
try {
|
|
57
|
+
if (this.tokenData) {
|
|
58
|
+
fs.writeFileSync(this.tokenFilePath, JSON.stringify(this.tokenData, null, 2))
|
|
59
|
+
// Set file permissions to be readable only by the owner
|
|
60
|
+
fs.chmodSync(this.tokenFilePath, 0o600)
|
|
61
|
+
} else {
|
|
62
|
+
// If token data is null, remove the file
|
|
63
|
+
if (fs.existsSync(this.tokenFilePath)) {
|
|
64
|
+
fs.unlinkSync(this.tokenFilePath)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(chalk.dim('Failed to save authentication token'))
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get the current access token
|
|
74
|
+
* @returns The access token or null if not available
|
|
75
|
+
*/
|
|
76
|
+
public getAccessToken(): string | null {
|
|
77
|
+
if (!this.tokenData) return null
|
|
78
|
+
return this.tokenData.access_token
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get the refresh token
|
|
83
|
+
* @returns The refresh token or null if not available
|
|
84
|
+
*/
|
|
85
|
+
public getRefreshToken(): string | null {
|
|
86
|
+
if (!this.tokenData) return null
|
|
87
|
+
return this.tokenData.refresh_token
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Check if the access token is expired
|
|
92
|
+
* @returns true if expired or about to expire (within 5 minutes), false otherwise
|
|
93
|
+
*/
|
|
94
|
+
public isTokenExpired(): boolean {
|
|
95
|
+
if (!this.tokenData || !this.tokenData.expires_at) return true
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
// Consider token expired if it's within 10 minutes of expiration
|
|
99
|
+
// Using a larger buffer to be more proactive about refreshing
|
|
100
|
+
const expirationBuffer = 10 * 60 * 1000 // 10 minutes in milliseconds
|
|
101
|
+
const isExpired = Date.now() + expirationBuffer >= this.tokenData.expires_at;
|
|
102
|
+
|
|
103
|
+
if (isExpired && process.argv.includes('--debug')) {
|
|
104
|
+
console.log(chalk.yellow(`DEBUG: Token expired or expiring soon. Current time: ${new Date().toISOString()}, Expiry: ${new Date(this.tokenData.expires_at).toISOString()}`));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return isExpired;
|
|
108
|
+
} catch (error) {
|
|
109
|
+
// If there's any error checking expiration, assume token is expired
|
|
110
|
+
console.error(chalk.dim(`Error checking token expiration: ${error instanceof Error ? error.message : String(error)}`));
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Set new token data
|
|
117
|
+
* @param accessToken The new access token
|
|
118
|
+
* @param refreshToken The new refresh token
|
|
119
|
+
* @param expiresIn Expiration time in seconds
|
|
120
|
+
*/
|
|
121
|
+
public setTokens(accessToken: string, refreshToken: string, expiresIn: number): void {
|
|
122
|
+
this.tokenData = {
|
|
123
|
+
access_token: accessToken,
|
|
124
|
+
refresh_token: refreshToken,
|
|
125
|
+
expires_at: Date.now() + (expiresIn * 1000)
|
|
126
|
+
}
|
|
127
|
+
this.saveToken()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Update just the access token and its expiration
|
|
132
|
+
* @param accessToken The new access token
|
|
133
|
+
* @param expiresIn Expiration time in seconds
|
|
134
|
+
*/
|
|
135
|
+
public updateAccessToken(accessToken: string, expiresIn: number): void {
|
|
136
|
+
if (!this.tokenData) return
|
|
137
|
+
|
|
138
|
+
this.tokenData.access_token = accessToken
|
|
139
|
+
this.tokenData.expires_at = Date.now() + (expiresIn * 1000)
|
|
140
|
+
this.saveToken()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Clear all token data
|
|
145
|
+
*/
|
|
146
|
+
public clearTokens(): void {
|
|
147
|
+
this.tokenData = null
|
|
148
|
+
this.saveToken()
|
|
149
|
+
}
|
|
150
|
+
}
|