sealos-cli 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 +77 -76
- package/dist/bin/cli.cjs +5120 -775
- package/dist/bin/cli.mjs +5120 -775
- package/dist/main.cjs +5116 -775
- package/dist/main.mjs +5120 -775
- package/package.json +6 -5
- package/src/commands/app/index.ts +5 -4
- package/src/commands/database/index.ts +12 -12
- package/src/commands/devbox/index.ts +676 -183
- package/src/commands/quota/index.ts +4 -3
- package/src/commands/s3/index.ts +5 -5
- package/src/commands/template/index.ts +107 -41
- package/src/commands/workspace/index.ts +49 -39
- package/src/docs/database_openapi.json +21 -38
- package/src/docs/devbox_openapi.json +5760 -0
- package/src/docs/template_openapi.json +2661 -1
- package/src/generated/database.ts +1 -5
- package/src/generated/devbox.ts +2500 -0
- package/src/generated/template.ts +228 -0
- package/src/lib/api-client.ts +19 -1
- package/src/lib/auth.ts +17 -8
- package/src/lib/errors.ts +1 -1
- package/src/lib/output.ts +5 -6
- package/src/main.ts +4 -11
- package/src/types/index.ts +0 -12
- package/src/commands/config/index.ts +0 -54
- package/src/lib/api.ts +0 -83
- package/src/lib/config.ts +0 -134
|
@@ -104,6 +104,26 @@ export interface paths {
|
|
|
104
104
|
patch?: never;
|
|
105
105
|
trace?: never;
|
|
106
106
|
};
|
|
107
|
+
"/templates/instances/{instanceName}": {
|
|
108
|
+
parameters: {
|
|
109
|
+
query?: never;
|
|
110
|
+
header?: never;
|
|
111
|
+
path?: never;
|
|
112
|
+
cookie?: never;
|
|
113
|
+
};
|
|
114
|
+
get?: never;
|
|
115
|
+
put?: never;
|
|
116
|
+
post?: never;
|
|
117
|
+
/**
|
|
118
|
+
* Delete template instance
|
|
119
|
+
* @description Deletes a deployed template instance from the user namespace. Instances created with ownerReferences enabled delete their explicit PVCs first and then delete the Instance so Kubernetes garbage collection removes owned dependents. Legacy instances without the ownerReferences-ready marker use the comprehensive label-selector cleanup path before deleting the Instance.
|
|
120
|
+
*/
|
|
121
|
+
delete: operations["deleteInstance"];
|
|
122
|
+
options?: never;
|
|
123
|
+
head?: never;
|
|
124
|
+
patch?: never;
|
|
125
|
+
trace?: never;
|
|
126
|
+
};
|
|
107
127
|
}
|
|
108
128
|
export type webhooks = Record<string, never>;
|
|
109
129
|
export interface components {
|
|
@@ -1004,4 +1024,212 @@ export interface operations {
|
|
|
1004
1024
|
};
|
|
1005
1025
|
};
|
|
1006
1026
|
};
|
|
1027
|
+
deleteInstance: {
|
|
1028
|
+
parameters: {
|
|
1029
|
+
query?: never;
|
|
1030
|
+
header?: never;
|
|
1031
|
+
path: {
|
|
1032
|
+
/** @description Name of the deployed template instance to delete (must exist in user namespace) */
|
|
1033
|
+
instanceName: string;
|
|
1034
|
+
};
|
|
1035
|
+
cookie?: never;
|
|
1036
|
+
};
|
|
1037
|
+
requestBody?: never;
|
|
1038
|
+
responses: {
|
|
1039
|
+
/** @description Instance deleted successfully. No response body. */
|
|
1040
|
+
204: {
|
|
1041
|
+
headers: {
|
|
1042
|
+
[name: string]: unknown;
|
|
1043
|
+
};
|
|
1044
|
+
content?: never;
|
|
1045
|
+
};
|
|
1046
|
+
/** @description Bad request - invalid instance name parameter */
|
|
1047
|
+
400: {
|
|
1048
|
+
headers: {
|
|
1049
|
+
[name: string]: unknown;
|
|
1050
|
+
};
|
|
1051
|
+
content: {
|
|
1052
|
+
"application/json": {
|
|
1053
|
+
error: {
|
|
1054
|
+
/**
|
|
1055
|
+
* @description High-level error type for categorization
|
|
1056
|
+
* @enum {string}
|
|
1057
|
+
*/
|
|
1058
|
+
type: "validation_error";
|
|
1059
|
+
/**
|
|
1060
|
+
* @description Specific error code for programmatic handling and i18n
|
|
1061
|
+
* @enum {string}
|
|
1062
|
+
*/
|
|
1063
|
+
code: "INVALID_PARAMETER";
|
|
1064
|
+
/** @description Human-readable error message */
|
|
1065
|
+
message: string;
|
|
1066
|
+
/** @description For INVALID_PARAMETER: Array<{ field, message }>. For INVALID_VALUE: optional string. Omitted for other codes. */
|
|
1067
|
+
details?: {
|
|
1068
|
+
/** @description Field path using dot/bracket notation, e.g. "ports[0].number" */
|
|
1069
|
+
field: string;
|
|
1070
|
+
/** @description Validation error message for this field */
|
|
1071
|
+
message: string;
|
|
1072
|
+
}[] | string;
|
|
1073
|
+
};
|
|
1074
|
+
};
|
|
1075
|
+
};
|
|
1076
|
+
};
|
|
1077
|
+
/** @description Unauthorized - Missing or invalid kubeconfig */
|
|
1078
|
+
401: {
|
|
1079
|
+
headers: {
|
|
1080
|
+
[name: string]: unknown;
|
|
1081
|
+
};
|
|
1082
|
+
content: {
|
|
1083
|
+
"application/json": {
|
|
1084
|
+
error: {
|
|
1085
|
+
/**
|
|
1086
|
+
* @description High-level error type for categorization
|
|
1087
|
+
* @constant
|
|
1088
|
+
*/
|
|
1089
|
+
type: "authentication_error";
|
|
1090
|
+
/**
|
|
1091
|
+
* @description Specific error code for programmatic handling and i18n
|
|
1092
|
+
* @constant
|
|
1093
|
+
*/
|
|
1094
|
+
code: "AUTHENTICATION_REQUIRED";
|
|
1095
|
+
/** @description Human-readable error message */
|
|
1096
|
+
message: string;
|
|
1097
|
+
/** @description Typically omitted. May contain additional context in edge cases. */
|
|
1098
|
+
details?: string;
|
|
1099
|
+
};
|
|
1100
|
+
};
|
|
1101
|
+
};
|
|
1102
|
+
};
|
|
1103
|
+
/** @description Forbidden - Insufficient permissions */
|
|
1104
|
+
403: {
|
|
1105
|
+
headers: {
|
|
1106
|
+
[name: string]: unknown;
|
|
1107
|
+
};
|
|
1108
|
+
content: {
|
|
1109
|
+
"application/json": {
|
|
1110
|
+
error: {
|
|
1111
|
+
/**
|
|
1112
|
+
* @description High-level error type for categorization
|
|
1113
|
+
* @constant
|
|
1114
|
+
*/
|
|
1115
|
+
type: "authorization_error";
|
|
1116
|
+
/**
|
|
1117
|
+
* @description Specific error code for programmatic handling and i18n
|
|
1118
|
+
* @enum {string}
|
|
1119
|
+
*/
|
|
1120
|
+
code: "PERMISSION_DENIED";
|
|
1121
|
+
/** @description Human-readable error message */
|
|
1122
|
+
message: string;
|
|
1123
|
+
/** @description Typically omitted. May contain additional context in edge cases. */
|
|
1124
|
+
details?: string;
|
|
1125
|
+
};
|
|
1126
|
+
};
|
|
1127
|
+
};
|
|
1128
|
+
};
|
|
1129
|
+
/** @description Not Found - Instance not found */
|
|
1130
|
+
404: {
|
|
1131
|
+
headers: {
|
|
1132
|
+
[name: string]: unknown;
|
|
1133
|
+
};
|
|
1134
|
+
content: {
|
|
1135
|
+
"application/json": {
|
|
1136
|
+
error: {
|
|
1137
|
+
/**
|
|
1138
|
+
* @description High-level error type for categorization
|
|
1139
|
+
* @constant
|
|
1140
|
+
*/
|
|
1141
|
+
type: "resource_error";
|
|
1142
|
+
/**
|
|
1143
|
+
* @description Specific error code for programmatic handling and i18n
|
|
1144
|
+
* @constant
|
|
1145
|
+
*/
|
|
1146
|
+
code: "NOT_FOUND";
|
|
1147
|
+
/** @description Human-readable error message */
|
|
1148
|
+
message: string;
|
|
1149
|
+
/** @description Typically omitted. May contain additional context in edge cases. */
|
|
1150
|
+
details?: string;
|
|
1151
|
+
};
|
|
1152
|
+
};
|
|
1153
|
+
};
|
|
1154
|
+
};
|
|
1155
|
+
/** @description Method Not Allowed */
|
|
1156
|
+
405: {
|
|
1157
|
+
headers: {
|
|
1158
|
+
[name: string]: unknown;
|
|
1159
|
+
};
|
|
1160
|
+
content: {
|
|
1161
|
+
"application/json": {
|
|
1162
|
+
error: {
|
|
1163
|
+
/**
|
|
1164
|
+
* @description High-level error type for categorization
|
|
1165
|
+
* @constant
|
|
1166
|
+
*/
|
|
1167
|
+
type: "client_error";
|
|
1168
|
+
/**
|
|
1169
|
+
* @description Specific error code for programmatic handling and i18n
|
|
1170
|
+
* @constant
|
|
1171
|
+
*/
|
|
1172
|
+
code: "METHOD_NOT_ALLOWED";
|
|
1173
|
+
/** @description Human-readable error message */
|
|
1174
|
+
message: string;
|
|
1175
|
+
/** @description Typically omitted. */
|
|
1176
|
+
details?: string;
|
|
1177
|
+
};
|
|
1178
|
+
};
|
|
1179
|
+
};
|
|
1180
|
+
};
|
|
1181
|
+
/** @description Internal Server Error - Kubernetes API error or unexpected failure */
|
|
1182
|
+
500: {
|
|
1183
|
+
headers: {
|
|
1184
|
+
[name: string]: unknown;
|
|
1185
|
+
};
|
|
1186
|
+
content: {
|
|
1187
|
+
"application/json": {
|
|
1188
|
+
error: {
|
|
1189
|
+
/**
|
|
1190
|
+
* @description High-level error type for categorization
|
|
1191
|
+
* @enum {string}
|
|
1192
|
+
*/
|
|
1193
|
+
type: "operation_error" | "internal_error";
|
|
1194
|
+
/**
|
|
1195
|
+
* @description Specific error code for programmatic handling and i18n
|
|
1196
|
+
* @enum {string}
|
|
1197
|
+
*/
|
|
1198
|
+
code: "KUBERNETES_ERROR" | "INTERNAL_ERROR";
|
|
1199
|
+
/** @description Human-readable error message */
|
|
1200
|
+
message: string;
|
|
1201
|
+
/** @description Raw error string from the underlying system, for troubleshooting. */
|
|
1202
|
+
details?: string;
|
|
1203
|
+
};
|
|
1204
|
+
};
|
|
1205
|
+
};
|
|
1206
|
+
};
|
|
1207
|
+
/** @description Service Unavailable - Kubernetes cluster temporarily unreachable */
|
|
1208
|
+
503: {
|
|
1209
|
+
headers: {
|
|
1210
|
+
[name: string]: unknown;
|
|
1211
|
+
};
|
|
1212
|
+
content: {
|
|
1213
|
+
"application/json": {
|
|
1214
|
+
error: {
|
|
1215
|
+
/**
|
|
1216
|
+
* @description High-level error type for categorization
|
|
1217
|
+
* @constant
|
|
1218
|
+
*/
|
|
1219
|
+
type: "internal_error";
|
|
1220
|
+
/**
|
|
1221
|
+
* @description Specific error code for programmatic handling and i18n
|
|
1222
|
+
* @constant
|
|
1223
|
+
*/
|
|
1224
|
+
code: "SERVICE_UNAVAILABLE";
|
|
1225
|
+
/** @description Human-readable error message */
|
|
1226
|
+
message: string;
|
|
1227
|
+
/** @description Raw connection error from the underlying system (e.g. ECONNREFUSED). */
|
|
1228
|
+
details?: string;
|
|
1229
|
+
};
|
|
1230
|
+
};
|
|
1231
|
+
};
|
|
1232
|
+
};
|
|
1233
|
+
};
|
|
1234
|
+
};
|
|
1007
1235
|
}
|
package/src/lib/api-client.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import createClient from 'openapi-fetch'
|
|
2
2
|
import type { paths as TemplatePaths } from '../generated/template.ts'
|
|
3
3
|
import type { paths as DatabasePaths } from '../generated/database.ts'
|
|
4
|
+
import type { paths as DevboxPaths } from '../generated/devbox.ts'
|
|
4
5
|
import { DEFAULT_SEALOS_REGION, loadAuth } from './auth.ts'
|
|
5
6
|
import { ConfigError } from './errors.ts'
|
|
6
7
|
|
|
@@ -14,7 +15,7 @@ function resolveHost (options?: { baseUrl?: string }): string {
|
|
|
14
15
|
|
|
15
16
|
const host = options?.baseUrl || process.env.SEALOS_REGION || authRegion || DEFAULT_SEALOS_REGION
|
|
16
17
|
if (!host) {
|
|
17
|
-
throw new ConfigError('No Sealos Cloud host configured. Run "sealos login <host>" first.')
|
|
18
|
+
throw new ConfigError('No Sealos Cloud host configured. Run "sealos-cli login <host>" first.')
|
|
18
19
|
}
|
|
19
20
|
return host.replace(/\/+$/, '')
|
|
20
21
|
}
|
|
@@ -27,6 +28,10 @@ export function resolveTemplateProviderHost (host: string): string {
|
|
|
27
28
|
return resolvePrefixedHost(host, 'template')
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
export function resolveDevboxProviderHost (host: string): string {
|
|
32
|
+
return resolvePrefixedHost(host, 'devbox')
|
|
33
|
+
}
|
|
34
|
+
|
|
30
35
|
function resolvePrefixedHost (host: string, prefix: string): string {
|
|
31
36
|
const url = new URL(host)
|
|
32
37
|
|
|
@@ -55,6 +60,15 @@ function resolveTemplateHost (options?: { baseUrl?: string }): string {
|
|
|
55
60
|
return resolveTemplateProviderHost(resolveHost(options))
|
|
56
61
|
}
|
|
57
62
|
|
|
63
|
+
function resolveDevboxHost (options?: { baseUrl?: string }): string {
|
|
64
|
+
const override = process.env.SEALOS_DEVBOX_HOST?.trim()
|
|
65
|
+
if (override) {
|
|
66
|
+
return override.replace(/\/+$/, '')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return resolveDevboxProviderHost(resolveHost(options))
|
|
70
|
+
}
|
|
71
|
+
|
|
58
72
|
export function createTemplateClient (options?: { baseUrl?: string }) {
|
|
59
73
|
return createClient<TemplatePaths>({ baseUrl: `${resolveTemplateHost(options)}/api/v2alpha` })
|
|
60
74
|
}
|
|
@@ -62,3 +76,7 @@ export function createTemplateClient (options?: { baseUrl?: string }) {
|
|
|
62
76
|
export function createDatabaseClient (options?: { baseUrl?: string }) {
|
|
63
77
|
return createClient<DatabasePaths>({ baseUrl: `${resolveDatabaseHost(options)}/api/v2alpha` })
|
|
64
78
|
}
|
|
79
|
+
|
|
80
|
+
export function createDevboxClient (options?: { baseUrl?: string }) {
|
|
81
|
+
return createClient<DevboxPaths>({ baseUrl: `${resolveDevboxHost(options)}/api/v2alpha` })
|
|
82
|
+
}
|
package/src/lib/auth.ts
CHANGED
|
@@ -141,13 +141,13 @@ export function saveAuth (auth: SealosAuthData, deps: AuthDependencies = {}): vo
|
|
|
141
141
|
export function loadAuth (deps: AuthDependencies = {}): SealosAuthData {
|
|
142
142
|
const { paths } = withDeps(deps)
|
|
143
143
|
if (!existsSync(paths.authPath)) {
|
|
144
|
-
throw new Error('Not authenticated. Please run: sealos login')
|
|
144
|
+
throw new Error('Not authenticated. Please run: sealos-cli login')
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
return JSON.parse(readFileSync(paths.authPath, 'utf-8')) as SealosAuthData
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
export function
|
|
150
|
+
export function getRegionalToken (deps: AuthDependencies = {}): string | null {
|
|
151
151
|
try {
|
|
152
152
|
return loadAuth(deps).regional_token || null
|
|
153
153
|
} catch {
|
|
@@ -155,15 +155,24 @@ export function getToken (deps: AuthDependencies = {}): string | null {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
export function getKubeconfigContent (deps: AuthDependencies = {}): string | null {
|
|
159
|
+
const { paths } = withDeps(deps)
|
|
160
|
+
try {
|
|
161
|
+
return readFileSync(paths.kubeconfigPath, 'utf-8')
|
|
162
|
+
} catch {
|
|
163
|
+
return null
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
158
167
|
export function getAuthHeaders (deps: AuthDependencies = {}): { Authorization: string } | null {
|
|
159
|
-
const
|
|
160
|
-
return
|
|
168
|
+
const kubeconfig = getKubeconfigContent(deps)
|
|
169
|
+
return kubeconfig ? { Authorization: encodeURIComponent(kubeconfig) } : null
|
|
161
170
|
}
|
|
162
171
|
|
|
163
172
|
export function requireAuth (deps: AuthDependencies = {}): { Authorization: string } {
|
|
164
173
|
const headers = getAuthHeaders(deps)
|
|
165
174
|
if (!headers) {
|
|
166
|
-
throw new Error('Authentication required. Please run "sealos login" first.')
|
|
175
|
+
throw new Error('Authentication required. Please run "sealos-cli login" first.')
|
|
167
176
|
}
|
|
168
177
|
return headers
|
|
169
178
|
}
|
|
@@ -487,7 +496,7 @@ export async function loginWithDeviceFlow (region?: string, deps: AuthDependenci
|
|
|
487
496
|
export async function listWorkspaces (deps: AuthDependencies = {}): Promise<WorkspaceListResult> {
|
|
488
497
|
const auth = loadAuth(deps)
|
|
489
498
|
if (!auth.regional_token) {
|
|
490
|
-
throw new Error('No regional_token found. Please run: sealos login')
|
|
499
|
+
throw new Error('No regional_token found. Please run: sealos-cli login')
|
|
491
500
|
}
|
|
492
501
|
|
|
493
502
|
const workspaces = await listRemoteWorkspaces(auth.region, auth.regional_token, deps)
|
|
@@ -505,13 +514,13 @@ export async function listWorkspaces (deps: AuthDependencies = {}): Promise<Work
|
|
|
505
514
|
|
|
506
515
|
export async function switchWorkspace (target: string, deps: AuthDependencies = {}): Promise<SwitchWorkspaceResult> {
|
|
507
516
|
if (!target) {
|
|
508
|
-
throw new Error('Usage: sealos auth switch <namespace-id-or-uid>')
|
|
517
|
+
throw new Error('Usage: sealos-cli auth switch <namespace-id-or-uid>')
|
|
509
518
|
}
|
|
510
519
|
|
|
511
520
|
const fullDeps = withDeps(deps)
|
|
512
521
|
const auth = loadAuth(fullDeps)
|
|
513
522
|
if (!auth.regional_token) {
|
|
514
|
-
throw new Error('No regional_token found. Please run: sealos login')
|
|
523
|
+
throw new Error('No regional_token found. Please run: sealos-cli login')
|
|
515
524
|
}
|
|
516
525
|
|
|
517
526
|
const workspaces = await listRemoteWorkspaces(auth.region, auth.regional_token, fullDeps)
|
package/src/lib/errors.ts
CHANGED
|
@@ -14,7 +14,7 @@ export class CliError extends Error {
|
|
|
14
14
|
* Authentication error
|
|
15
15
|
*/
|
|
16
16
|
export class AuthError extends CliError {
|
|
17
|
-
constructor (message: string = 'Authentication required. Please run "sealos login" first.') {
|
|
17
|
+
constructor (message: string = 'Authentication required. Please run "sealos-cli login" first.') {
|
|
18
18
|
super(message, 1)
|
|
19
19
|
this.name = 'AuthError'
|
|
20
20
|
}
|
package/src/lib/output.ts
CHANGED
|
@@ -10,12 +10,11 @@ export function outputJson (data: any): void {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Output YAML format
|
|
13
|
+
* Output YAML format.
|
|
14
|
+
* Generic YAML output is not part of the v1 command surface.
|
|
14
15
|
*/
|
|
15
|
-
export function outputYaml (
|
|
16
|
-
|
|
17
|
-
console.log('YAML output not implemented yet')
|
|
18
|
-
console.log(data)
|
|
16
|
+
export function outputYaml (_data: any): never {
|
|
17
|
+
throw new Error('YAML output is not supported in the v1 release. Use json or table output.')
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
/**
|
|
@@ -87,7 +86,7 @@ export function spinner (text: string): Ora {
|
|
|
87
86
|
* Confirmation prompt
|
|
88
87
|
*/
|
|
89
88
|
export async function confirm (message: string): Promise<boolean> {
|
|
90
|
-
//
|
|
89
|
+
// Non-interactive default for v1. Replace with a prompt implementation when needed.
|
|
91
90
|
console.log(chalk.yellow('?'), message)
|
|
92
91
|
return true
|
|
93
92
|
}
|
package/src/main.ts
CHANGED
|
@@ -3,32 +3,25 @@ import { Command } from 'commander'
|
|
|
3
3
|
import { registerAuthCommands } from './commands/auth/index.ts'
|
|
4
4
|
import { createWorkspaceCommand } from './commands/workspace/index.ts'
|
|
5
5
|
import { createDevboxCommand } from './commands/devbox/index.ts'
|
|
6
|
-
import { createS3Command } from './commands/s3/index.ts'
|
|
7
6
|
import { createDatabaseCommand } from './commands/database/index.ts'
|
|
8
7
|
import { createTemplateCommand } from './commands/template/index.ts'
|
|
9
|
-
import { createQuotaCommand } from './commands/quota/index.ts'
|
|
10
|
-
import { createAppCommand } from './commands/app/index.ts'
|
|
11
|
-
import { createConfigCommand } from './commands/config/index.ts'
|
|
12
8
|
import { handleError } from './lib/errors.ts'
|
|
9
|
+
import packageJson from '../package.json' with { type: 'json' }
|
|
13
10
|
|
|
14
11
|
export function createProgram (): Command {
|
|
15
12
|
const program = new Command()
|
|
16
13
|
|
|
17
14
|
program
|
|
18
|
-
.name('sealos')
|
|
19
|
-
.description('Official CLI tool for Sealos Cloud - Manage devbox,
|
|
20
|
-
.version(
|
|
15
|
+
.name('sealos-cli')
|
|
16
|
+
.description('Official CLI tool for Sealos Cloud - Manage devbox, databases, templates, auth, and workspaces')
|
|
17
|
+
.version(packageJson.version)
|
|
21
18
|
|
|
22
19
|
// Register all command modules
|
|
23
20
|
registerAuthCommands(program)
|
|
24
21
|
program.addCommand(createWorkspaceCommand())
|
|
25
22
|
program.addCommand(createDevboxCommand())
|
|
26
|
-
program.addCommand(createS3Command())
|
|
27
23
|
program.addCommand(createDatabaseCommand())
|
|
28
24
|
program.addCommand(createTemplateCommand())
|
|
29
|
-
program.addCommand(createQuotaCommand())
|
|
30
|
-
program.addCommand(createAppCommand())
|
|
31
|
-
program.addCommand(createConfigCommand())
|
|
32
25
|
|
|
33
26
|
return program
|
|
34
27
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
// Core type definitions
|
|
2
2
|
|
|
3
|
-
export interface SealosConfig {
|
|
4
|
-
currentContext: string
|
|
5
|
-
contexts: Context[]
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export interface Context {
|
|
9
|
-
name: string
|
|
10
|
-
host: string
|
|
11
|
-
token: string
|
|
12
|
-
workspace: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
3
|
export interface DevboxConfig {
|
|
16
4
|
name?: string
|
|
17
5
|
template: string
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander'
|
|
2
|
-
import { readConfig, setConfigValue, getConfigValue } from '../../lib/config.ts'
|
|
3
|
-
import { success, outputJson } from '../../lib/output.ts'
|
|
4
|
-
import { handleError } from '../../lib/errors.ts'
|
|
5
|
-
|
|
6
|
-
export function createConfigCommand (): Command {
|
|
7
|
-
const configCmd = new Command('config')
|
|
8
|
-
.description('Manage CLI configuration')
|
|
9
|
-
|
|
10
|
-
configCmd
|
|
11
|
-
.command('set')
|
|
12
|
-
.description('Set a config value')
|
|
13
|
-
.argument('<key>', 'Config key')
|
|
14
|
-
.argument('<value>', 'Config value')
|
|
15
|
-
.action(async (key, value) => {
|
|
16
|
-
try {
|
|
17
|
-
setConfigValue(key, value)
|
|
18
|
-
success(`Config ${key} set to ${value}`)
|
|
19
|
-
} catch (error) {
|
|
20
|
-
handleError(error)
|
|
21
|
-
}
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
configCmd
|
|
25
|
-
.command('get')
|
|
26
|
-
.description('Get a config value')
|
|
27
|
-
.argument('<key>', 'Config key')
|
|
28
|
-
.action(async (key) => {
|
|
29
|
-
try {
|
|
30
|
-
const value = getConfigValue(key)
|
|
31
|
-
if (value) {
|
|
32
|
-
console.log(value)
|
|
33
|
-
} else {
|
|
34
|
-
console.log(`Config key "${key}" not found`)
|
|
35
|
-
}
|
|
36
|
-
} catch (error) {
|
|
37
|
-
handleError(error)
|
|
38
|
-
}
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
configCmd
|
|
42
|
-
.command('list')
|
|
43
|
-
.description('List all config values')
|
|
44
|
-
.action(async () => {
|
|
45
|
-
try {
|
|
46
|
-
const config = readConfig()
|
|
47
|
-
outputJson(config)
|
|
48
|
-
} catch (error) {
|
|
49
|
-
handleError(error)
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
return configCmd
|
|
54
|
-
}
|
package/src/lib/api.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import axios, { type AxiosInstance, type AxiosRequestConfig } from 'axios'
|
|
2
|
-
import { getCurrentContext } from './config.ts'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* API client base class
|
|
6
|
-
*/
|
|
7
|
-
export class ApiClient {
|
|
8
|
-
private client: AxiosInstance
|
|
9
|
-
|
|
10
|
-
constructor (baseURL?: string) {
|
|
11
|
-
const context = getCurrentContext()
|
|
12
|
-
|
|
13
|
-
this.client = axios.create({
|
|
14
|
-
baseURL: baseURL || context?.host || '',
|
|
15
|
-
timeout: 30000,
|
|
16
|
-
headers: {
|
|
17
|
-
'Content-Type': 'application/json'
|
|
18
|
-
}
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
// Request interceptor - add auth token
|
|
22
|
-
this.client.interceptors.request.use(
|
|
23
|
-
(config) => {
|
|
24
|
-
const context = getCurrentContext()
|
|
25
|
-
if (context?.token) {
|
|
26
|
-
config.headers.Authorization = `Bearer ${context.token}`
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Support KUBECONFIG environment variable
|
|
30
|
-
const kubeconfig = process.env.KUBECONFIG
|
|
31
|
-
if (kubeconfig) {
|
|
32
|
-
config.headers['X-Kubeconfig'] = kubeconfig
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return config
|
|
36
|
-
},
|
|
37
|
-
async (error) => await Promise.reject(error)
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
// Response interceptor - unified error handling
|
|
41
|
-
this.client.interceptors.response.use(
|
|
42
|
-
(response) => response,
|
|
43
|
-
async (error) => {
|
|
44
|
-
if (error.response?.status === 401) {
|
|
45
|
-
throw new Error('Authentication failed. Please run "sealos login" first.')
|
|
46
|
-
}
|
|
47
|
-
return await Promise.reject(error)
|
|
48
|
-
}
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async get<T = any> (url: string, config?: AxiosRequestConfig): Promise<T> {
|
|
53
|
-
const response = await this.client.get<T>(url, config)
|
|
54
|
-
return response.data
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async post<T = any> (url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
|
|
58
|
-
const response = await this.client.post<T>(url, data, config)
|
|
59
|
-
return response.data
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async put<T = any> (url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
|
|
63
|
-
const response = await this.client.put<T>(url, data, config)
|
|
64
|
-
return response.data
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async delete<T = any> (url: string, config?: AxiosRequestConfig): Promise<T> {
|
|
68
|
-
const response = await this.client.delete<T>(url, config)
|
|
69
|
-
return response.data
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async patch<T = any> (url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
|
|
73
|
-
const response = await this.client.patch<T>(url, data, config)
|
|
74
|
-
return response.data
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Create API client instance
|
|
80
|
-
*/
|
|
81
|
-
export function createApiClient (baseURL?: string): ApiClient {
|
|
82
|
-
return new ApiClient(baseURL)
|
|
83
|
-
}
|