sealos-cli 0.1.0 → 1.0.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 +58 -47
- package/dist/bin/cli.cjs +4988 -767
- package/dist/bin/cli.mjs +4988 -767
- package/dist/main.cjs +4984 -767
- package/dist/main.mjs +4988 -767
- package/package.json +2 -2
- package/src/commands/database/index.ts +11 -11
- package/src/commands/devbox/index.ts +676 -183
- package/src/commands/template/index.ts +103 -37
- 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 +18 -0
- package/src/lib/auth.ts +12 -3
- package/src/main.ts +1 -9
- 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
|
|
|
@@ -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
|
@@ -147,7 +147,7 @@ export function loadAuth (deps: AuthDependencies = {}): SealosAuthData {
|
|
|
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,9 +155,18 @@ 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 } {
|
package/src/main.ts
CHANGED
|
@@ -3,12 +3,8 @@ 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'
|
|
13
9
|
|
|
14
10
|
export function createProgram (): Command {
|
|
@@ -16,19 +12,15 @@ export function createProgram (): Command {
|
|
|
16
12
|
|
|
17
13
|
program
|
|
18
14
|
.name('sealos')
|
|
19
|
-
.description('Official CLI tool for Sealos Cloud - Manage devbox,
|
|
15
|
+
.description('Official CLI tool for Sealos Cloud - Manage devbox, databases, templates, auth, and workspaces')
|
|
20
16
|
.version('0.0.1')
|
|
21
17
|
|
|
22
18
|
// Register all command modules
|
|
23
19
|
registerAuthCommands(program)
|
|
24
20
|
program.addCommand(createWorkspaceCommand())
|
|
25
21
|
program.addCommand(createDevboxCommand())
|
|
26
|
-
program.addCommand(createS3Command())
|
|
27
22
|
program.addCommand(createDatabaseCommand())
|
|
28
23
|
program.addCommand(createTemplateCommand())
|
|
29
|
-
program.addCommand(createQuotaCommand())
|
|
30
|
-
program.addCommand(createAppCommand())
|
|
31
|
-
program.addCommand(createConfigCommand())
|
|
32
24
|
|
|
33
25
|
return program
|
|
34
26
|
}
|
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
|
-
}
|
package/src/lib/config.ts
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { homedir } from 'node:os'
|
|
2
|
-
import { join } from 'node:path'
|
|
3
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs'
|
|
4
|
-
import type { SealosConfig, Context } from '../types/index.ts'
|
|
5
|
-
|
|
6
|
-
const CONFIG_DIR = join(homedir(), '.sealos')
|
|
7
|
-
const CONFIG_FILE = join(CONFIG_DIR, 'config.json')
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Ensure config directory exists
|
|
11
|
-
*/
|
|
12
|
-
export function ensureConfigDir (): void {
|
|
13
|
-
if (!existsSync(CONFIG_DIR)) {
|
|
14
|
-
mkdirSync(CONFIG_DIR, { recursive: true })
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Read config file
|
|
20
|
-
*/
|
|
21
|
-
export function readConfig (): SealosConfig {
|
|
22
|
-
ensureConfigDir()
|
|
23
|
-
|
|
24
|
-
if (!existsSync(CONFIG_FILE)) {
|
|
25
|
-
const defaultConfig: SealosConfig = {
|
|
26
|
-
currentContext: '',
|
|
27
|
-
contexts: []
|
|
28
|
-
}
|
|
29
|
-
return defaultConfig
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const content = readFileSync(CONFIG_FILE, 'utf-8')
|
|
34
|
-
return JSON.parse(content) as SealosConfig
|
|
35
|
-
} catch (error) {
|
|
36
|
-
throw new Error(`Failed to read config file: ${error}`)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Write config file
|
|
42
|
-
*/
|
|
43
|
-
export function writeConfig (config: SealosConfig): void {
|
|
44
|
-
ensureConfigDir()
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8')
|
|
48
|
-
} catch (error) {
|
|
49
|
-
throw new Error(`Failed to write config file: ${error}`)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Get current context
|
|
55
|
-
*/
|
|
56
|
-
export function getCurrentContext (): Context | null {
|
|
57
|
-
const config = readConfig()
|
|
58
|
-
if (!config.currentContext) {
|
|
59
|
-
return null
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const context = config.contexts.find(ctx => ctx.name === config.currentContext)
|
|
63
|
-
return context || null
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Set current context
|
|
68
|
-
*/
|
|
69
|
-
export function setCurrentContext (name: string): void {
|
|
70
|
-
const config = readConfig()
|
|
71
|
-
const context = config.contexts.find(ctx => ctx.name === name)
|
|
72
|
-
|
|
73
|
-
if (!context) {
|
|
74
|
-
throw new Error(`Context "${name}" not found`)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
config.currentContext = name
|
|
78
|
-
writeConfig(config)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Add or update context
|
|
83
|
-
*/
|
|
84
|
-
export function upsertContext (context: Context): void {
|
|
85
|
-
const config = readConfig()
|
|
86
|
-
const existingIndex = config.contexts.findIndex(ctx => ctx.name === context.name)
|
|
87
|
-
|
|
88
|
-
if (existingIndex >= 0) {
|
|
89
|
-
config.contexts[existingIndex] = context
|
|
90
|
-
} else {
|
|
91
|
-
config.contexts.push(context)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// If this is the first context, set it as current automatically
|
|
95
|
-
if (!config.currentContext) {
|
|
96
|
-
config.currentContext = context.name
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
writeConfig(config)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Remove context
|
|
104
|
-
*/
|
|
105
|
-
export function removeContext (name: string): void {
|
|
106
|
-
const config = readConfig()
|
|
107
|
-
config.contexts = config.contexts.filter(ctx => ctx.name !== name)
|
|
108
|
-
|
|
109
|
-
// If removing current context, clear currentContext
|
|
110
|
-
if (config.currentContext === name) {
|
|
111
|
-
config.currentContext = config.contexts[0]?.name || ''
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
writeConfig(config)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Get config value
|
|
119
|
-
*/
|
|
120
|
-
export function getConfigValue (key: string): string | undefined {
|
|
121
|
-
const config = readConfig()
|
|
122
|
-
// TODO: Implement nested key access, e.g. "contexts.0.name"
|
|
123
|
-
return (config as unknown as Record<string, unknown>)[key] as string | undefined
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Set config value
|
|
128
|
-
*/
|
|
129
|
-
export function setConfigValue (key: string, value: string): void {
|
|
130
|
-
const config = readConfig()
|
|
131
|
-
// TODO: Implement nested key setting
|
|
132
|
-
;(config as unknown as Record<string, unknown>)[key] = value
|
|
133
|
-
writeConfig(config)
|
|
134
|
-
}
|