sealos-cli 1.1.1 → 1.1.2
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 +7 -3
- package/dist/bin/cli.cjs +1219 -982
- package/dist/bin/cli.mjs +1217 -980
- package/dist/main.cjs +1219 -982
- package/dist/main.mjs +1217 -980
- package/package.json +1 -1
- package/src/commands/auth/index.ts +2 -2
- package/src/commands/auth/login.ts +1 -1
- package/src/commands/auth/logout.ts +21 -2
- package/src/commands/auth/whoami.ts +1 -1
- package/src/commands/database/index.ts +142 -18
- package/src/commands/devbox/index.ts +108 -24
- package/src/commands/template/index.ts +28 -3
- package/src/commands/workspace/index.ts +3 -3
- package/src/lib/auth.ts +17 -1
package/dist/main.mjs
CHANGED
|
@@ -20,938 +20,1031 @@ import { execFileSync } from "child_process";
|
|
|
20
20
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
21
21
|
import { homedir, platform } from "os";
|
|
22
22
|
import { join } from "path";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
var
|
|
26
|
-
var
|
|
27
|
-
var
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
23
|
+
|
|
24
|
+
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
25
|
+
var ANSI_BACKGROUND_OFFSET = 10;
|
|
26
|
+
var wrapAnsi16 = /* @__PURE__ */ __name((offset = 0) => (code) => `\x1B[${code + offset}m`, "wrapAnsi16");
|
|
27
|
+
var wrapAnsi256 = /* @__PURE__ */ __name((offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`, "wrapAnsi256");
|
|
28
|
+
var wrapAnsi16m = /* @__PURE__ */ __name((offset = 0) => (red2, green2, blue2) => `\x1B[${38 + offset};2;${red2};${green2};${blue2}m`, "wrapAnsi16m");
|
|
29
|
+
var styles = {
|
|
30
|
+
modifier: {
|
|
31
|
+
reset: [0, 0],
|
|
32
|
+
// 21 isn't widely supported and 22 does the same thing
|
|
33
|
+
bold: [1, 22],
|
|
34
|
+
dim: [2, 22],
|
|
35
|
+
italic: [3, 23],
|
|
36
|
+
underline: [4, 24],
|
|
37
|
+
overline: [53, 55],
|
|
38
|
+
inverse: [7, 27],
|
|
39
|
+
hidden: [8, 28],
|
|
40
|
+
strikethrough: [9, 29]
|
|
41
|
+
},
|
|
42
|
+
color: {
|
|
43
|
+
black: [30, 39],
|
|
44
|
+
red: [31, 39],
|
|
45
|
+
green: [32, 39],
|
|
46
|
+
yellow: [33, 39],
|
|
47
|
+
blue: [34, 39],
|
|
48
|
+
magenta: [35, 39],
|
|
49
|
+
cyan: [36, 39],
|
|
50
|
+
white: [37, 39],
|
|
51
|
+
// Bright color
|
|
52
|
+
blackBright: [90, 39],
|
|
53
|
+
gray: [90, 39],
|
|
54
|
+
// Alias of `blackBright`
|
|
55
|
+
grey: [90, 39],
|
|
56
|
+
// Alias of `blackBright`
|
|
57
|
+
redBright: [91, 39],
|
|
58
|
+
greenBright: [92, 39],
|
|
59
|
+
yellowBright: [93, 39],
|
|
60
|
+
blueBright: [94, 39],
|
|
61
|
+
magentaBright: [95, 39],
|
|
62
|
+
cyanBright: [96, 39],
|
|
63
|
+
whiteBright: [97, 39]
|
|
64
|
+
},
|
|
65
|
+
bgColor: {
|
|
66
|
+
bgBlack: [40, 49],
|
|
67
|
+
bgRed: [41, 49],
|
|
68
|
+
bgGreen: [42, 49],
|
|
69
|
+
bgYellow: [43, 49],
|
|
70
|
+
bgBlue: [44, 49],
|
|
71
|
+
bgMagenta: [45, 49],
|
|
72
|
+
bgCyan: [46, 49],
|
|
73
|
+
bgWhite: [47, 49],
|
|
74
|
+
// Bright color
|
|
75
|
+
bgBlackBright: [100, 49],
|
|
76
|
+
bgGray: [100, 49],
|
|
77
|
+
// Alias of `bgBlackBright`
|
|
78
|
+
bgGrey: [100, 49],
|
|
79
|
+
// Alias of `bgBlackBright`
|
|
80
|
+
bgRedBright: [101, 49],
|
|
81
|
+
bgGreenBright: [102, 49],
|
|
82
|
+
bgYellowBright: [103, 49],
|
|
83
|
+
bgBlueBright: [104, 49],
|
|
84
|
+
bgMagentaBright: [105, 49],
|
|
85
|
+
bgCyanBright: [106, 49],
|
|
86
|
+
bgWhiteBright: [107, 49]
|
|
82
87
|
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
};
|
|
89
|
+
var modifierNames = Object.keys(styles.modifier);
|
|
90
|
+
var foregroundColorNames = Object.keys(styles.color);
|
|
91
|
+
var backgroundColorNames = Object.keys(styles.bgColor);
|
|
92
|
+
var colorNames = [...foregroundColorNames, ...backgroundColorNames];
|
|
93
|
+
function assembleStyles() {
|
|
94
|
+
const codes = /* @__PURE__ */ new Map();
|
|
95
|
+
for (const [groupName, group] of Object.entries(styles)) {
|
|
96
|
+
for (const [styleName, style] of Object.entries(group)) {
|
|
97
|
+
styles[styleName] = {
|
|
98
|
+
open: `\x1B[${style[0]}m`,
|
|
99
|
+
close: `\x1B[${style[1]}m`
|
|
100
|
+
};
|
|
101
|
+
group[styleName] = styles[styleName];
|
|
102
|
+
codes.set(style[0], style[1]);
|
|
103
|
+
}
|
|
104
|
+
Object.defineProperty(styles, groupName, {
|
|
105
|
+
value: group,
|
|
106
|
+
enumerable: false
|
|
107
|
+
});
|
|
94
108
|
}
|
|
95
|
-
|
|
109
|
+
Object.defineProperty(styles, "codes", {
|
|
110
|
+
value: codes,
|
|
111
|
+
enumerable: false
|
|
112
|
+
});
|
|
113
|
+
styles.color.close = "\x1B[39m";
|
|
114
|
+
styles.bgColor.close = "\x1B[49m";
|
|
115
|
+
styles.color.ansi = wrapAnsi16();
|
|
116
|
+
styles.color.ansi256 = wrapAnsi256();
|
|
117
|
+
styles.color.ansi16m = wrapAnsi16m();
|
|
118
|
+
styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
|
|
119
|
+
styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
|
|
120
|
+
styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
|
121
|
+
Object.defineProperties(styles, {
|
|
122
|
+
rgbToAnsi256: {
|
|
123
|
+
value(red2, green2, blue2) {
|
|
124
|
+
if (red2 === green2 && green2 === blue2) {
|
|
125
|
+
if (red2 < 8) {
|
|
126
|
+
return 16;
|
|
127
|
+
}
|
|
128
|
+
if (red2 > 248) {
|
|
129
|
+
return 231;
|
|
130
|
+
}
|
|
131
|
+
return Math.round((red2 - 8) / 247 * 24) + 232;
|
|
132
|
+
}
|
|
133
|
+
return 16 + 36 * Math.round(red2 / 255 * 5) + 6 * Math.round(green2 / 255 * 5) + Math.round(blue2 / 255 * 5);
|
|
134
|
+
},
|
|
135
|
+
enumerable: false
|
|
136
|
+
},
|
|
137
|
+
hexToRgb: {
|
|
138
|
+
value(hex) {
|
|
139
|
+
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
|
|
140
|
+
if (!matches) {
|
|
141
|
+
return [0, 0, 0];
|
|
142
|
+
}
|
|
143
|
+
let [colorString] = matches;
|
|
144
|
+
if (colorString.length === 3) {
|
|
145
|
+
colorString = [...colorString].map((character) => character + character).join("");
|
|
146
|
+
}
|
|
147
|
+
const integer = Number.parseInt(colorString, 16);
|
|
148
|
+
return [
|
|
149
|
+
/* eslint-disable no-bitwise */
|
|
150
|
+
integer >> 16 & 255,
|
|
151
|
+
integer >> 8 & 255,
|
|
152
|
+
integer & 255
|
|
153
|
+
/* eslint-enable no-bitwise */
|
|
154
|
+
];
|
|
155
|
+
},
|
|
156
|
+
enumerable: false
|
|
157
|
+
},
|
|
158
|
+
hexToAnsi256: {
|
|
159
|
+
value: /* @__PURE__ */ __name((hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)), "value"),
|
|
160
|
+
enumerable: false
|
|
161
|
+
},
|
|
162
|
+
ansi256ToAnsi: {
|
|
163
|
+
value(code) {
|
|
164
|
+
if (code < 8) {
|
|
165
|
+
return 30 + code;
|
|
166
|
+
}
|
|
167
|
+
if (code < 16) {
|
|
168
|
+
return 90 + (code - 8);
|
|
169
|
+
}
|
|
170
|
+
let red2;
|
|
171
|
+
let green2;
|
|
172
|
+
let blue2;
|
|
173
|
+
if (code >= 232) {
|
|
174
|
+
red2 = ((code - 232) * 10 + 8) / 255;
|
|
175
|
+
green2 = red2;
|
|
176
|
+
blue2 = red2;
|
|
177
|
+
} else {
|
|
178
|
+
code -= 16;
|
|
179
|
+
const remainder = code % 36;
|
|
180
|
+
red2 = Math.floor(code / 36) / 5;
|
|
181
|
+
green2 = Math.floor(remainder / 6) / 5;
|
|
182
|
+
blue2 = remainder % 6 / 5;
|
|
183
|
+
}
|
|
184
|
+
const value = Math.max(red2, green2, blue2) * 2;
|
|
185
|
+
if (value === 0) {
|
|
186
|
+
return 30;
|
|
187
|
+
}
|
|
188
|
+
let result = 30 + (Math.round(blue2) << 2 | Math.round(green2) << 1 | Math.round(red2));
|
|
189
|
+
if (value === 2) {
|
|
190
|
+
result += 60;
|
|
191
|
+
}
|
|
192
|
+
return result;
|
|
193
|
+
},
|
|
194
|
+
enumerable: false
|
|
195
|
+
},
|
|
196
|
+
rgbToAnsi: {
|
|
197
|
+
value: /* @__PURE__ */ __name((red2, green2, blue2) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red2, green2, blue2)), "value"),
|
|
198
|
+
enumerable: false
|
|
199
|
+
},
|
|
200
|
+
hexToAnsi: {
|
|
201
|
+
value: /* @__PURE__ */ __name((hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)), "value"),
|
|
202
|
+
enumerable: false
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
return styles;
|
|
96
206
|
}
|
|
97
|
-
__name(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
207
|
+
__name(assembleStyles, "assembleStyles");
|
|
208
|
+
var ansiStyles = assembleStyles();
|
|
209
|
+
var ansi_styles_default = ansiStyles;
|
|
210
|
+
|
|
211
|
+
// node_modules/chalk/source/vendor/supports-color/index.js
|
|
212
|
+
import process2 from "process";
|
|
213
|
+
import os from "os";
|
|
214
|
+
import tty from "tty";
|
|
215
|
+
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
|
|
216
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
217
|
+
const position = argv.indexOf(prefix + flag);
|
|
218
|
+
const terminatorPosition = argv.indexOf("--");
|
|
219
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
102
220
|
}
|
|
103
|
-
__name(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
221
|
+
__name(hasFlag, "hasFlag");
|
|
222
|
+
var { env } = process2;
|
|
223
|
+
var flagForceColor;
|
|
224
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
225
|
+
flagForceColor = 0;
|
|
226
|
+
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
227
|
+
flagForceColor = 1;
|
|
108
228
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return { authenticated: false };
|
|
114
|
-
}
|
|
115
|
-
try {
|
|
116
|
-
const kubeconfig = readFileSync(paths.kubeconfigPath, "utf-8");
|
|
117
|
-
if (!kubeconfig.includes("server:") || !kubeconfig.includes("token:") && !kubeconfig.includes("client-certificate")) {
|
|
118
|
-
return { authenticated: false };
|
|
229
|
+
function envForceColor() {
|
|
230
|
+
if ("FORCE_COLOR" in env) {
|
|
231
|
+
if (env.FORCE_COLOR === "true") {
|
|
232
|
+
return 1;
|
|
119
233
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
region: auth.region || "unknown",
|
|
125
|
-
workspace: auth.current_workspace?.id || "unknown"
|
|
126
|
-
};
|
|
127
|
-
} catch {
|
|
128
|
-
return { authenticated: false };
|
|
234
|
+
if (env.FORCE_COLOR === "false") {
|
|
235
|
+
return 0;
|
|
236
|
+
}
|
|
237
|
+
return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
|
129
238
|
}
|
|
130
239
|
}
|
|
131
|
-
__name(
|
|
132
|
-
function
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (!status.authenticated) {
|
|
136
|
-
return { authenticated: false };
|
|
240
|
+
__name(envForceColor, "envForceColor");
|
|
241
|
+
function translateLevel(level) {
|
|
242
|
+
if (level === 0) {
|
|
243
|
+
return false;
|
|
137
244
|
}
|
|
138
|
-
const auth = existsSync(paths.authPath) ? JSON.parse(readFileSync(paths.authPath, "utf-8")) : {};
|
|
139
245
|
return {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
246
|
+
level,
|
|
247
|
+
hasBasic: true,
|
|
248
|
+
has256: level >= 2,
|
|
249
|
+
has16m: level >= 3
|
|
144
250
|
};
|
|
145
251
|
}
|
|
146
|
-
__name(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
async function readErrorBody(res) {
|
|
152
|
-
return await res.text().catch(() => "");
|
|
153
|
-
}
|
|
154
|
-
__name(readErrorBody, "readErrorBody");
|
|
155
|
-
async function requestDeviceAuthorization(region, deps = {}) {
|
|
156
|
-
const { fetch: fetchImpl } = withDeps(deps);
|
|
157
|
-
const res = await fetchImpl(`${region}/api/auth/oauth2/device`, {
|
|
158
|
-
method: "POST",
|
|
159
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
160
|
-
body: new URLSearchParams({
|
|
161
|
-
client_id: SEALOS_AUTH_CLIENT_ID,
|
|
162
|
-
grant_type: DEVICE_GRANT_TYPE
|
|
163
|
-
})
|
|
164
|
-
});
|
|
165
|
-
if (!res.ok) {
|
|
166
|
-
const body = await readErrorBody(res);
|
|
167
|
-
throw new Error(`Device authorization request failed (${res.status}): ${body || res.statusText}`);
|
|
252
|
+
__name(translateLevel, "translateLevel");
|
|
253
|
+
function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
254
|
+
const noFlagForceColor = envForceColor();
|
|
255
|
+
if (noFlagForceColor !== void 0) {
|
|
256
|
+
flagForceColor = noFlagForceColor;
|
|
168
257
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
let pollInterval = interval * 1e3;
|
|
177
|
-
let lastLoggedMinute = -1;
|
|
178
|
-
while (now().getTime() < deadline) {
|
|
179
|
-
await sleep(pollInterval);
|
|
180
|
-
const remaining = Math.ceil((deadline - now().getTime()) / 6e4);
|
|
181
|
-
if (remaining !== lastLoggedMinute && remaining > 0) {
|
|
182
|
-
lastLoggedMinute = remaining;
|
|
183
|
-
stderr.write(` Waiting for authorization... (${remaining} min remaining)
|
|
184
|
-
`);
|
|
258
|
+
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
259
|
+
if (forceColor === 0) {
|
|
260
|
+
return 0;
|
|
261
|
+
}
|
|
262
|
+
if (sniffFlags) {
|
|
263
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
264
|
+
return 3;
|
|
185
265
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
189
|
-
body: new URLSearchParams({
|
|
190
|
-
client_id: SEALOS_AUTH_CLIENT_ID,
|
|
191
|
-
grant_type: DEVICE_GRANT_TYPE,
|
|
192
|
-
device_code: deviceCode
|
|
193
|
-
})
|
|
194
|
-
});
|
|
195
|
-
if (res.ok) {
|
|
196
|
-
return await parseResponse(res);
|
|
266
|
+
if (hasFlag("color=256")) {
|
|
267
|
+
return 2;
|
|
197
268
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
269
|
+
}
|
|
270
|
+
if ("TF_BUILD" in env && "AGENT_NAME" in env) {
|
|
271
|
+
return 1;
|
|
272
|
+
}
|
|
273
|
+
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
274
|
+
return 0;
|
|
275
|
+
}
|
|
276
|
+
const min = forceColor || 0;
|
|
277
|
+
if (env.TERM === "dumb") {
|
|
278
|
+
return min;
|
|
279
|
+
}
|
|
280
|
+
if (process2.platform === "win32") {
|
|
281
|
+
const osRelease = os.release().split(".");
|
|
282
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
283
|
+
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
211
284
|
}
|
|
285
|
+
return 1;
|
|
286
|
+
}
|
|
287
|
+
if ("CI" in env) {
|
|
288
|
+
if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => key in env)) {
|
|
289
|
+
return 3;
|
|
290
|
+
}
|
|
291
|
+
if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
|
|
292
|
+
return 1;
|
|
293
|
+
}
|
|
294
|
+
return min;
|
|
295
|
+
}
|
|
296
|
+
if ("TEAMCITY_VERSION" in env) {
|
|
297
|
+
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
298
|
+
}
|
|
299
|
+
if (env.COLORTERM === "truecolor") {
|
|
300
|
+
return 3;
|
|
212
301
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
302
|
+
if (env.TERM === "xterm-kitty") {
|
|
303
|
+
return 3;
|
|
304
|
+
}
|
|
305
|
+
if (env.TERM === "xterm-ghostty") {
|
|
306
|
+
return 3;
|
|
307
|
+
}
|
|
308
|
+
if (env.TERM === "wezterm") {
|
|
309
|
+
return 3;
|
|
310
|
+
}
|
|
311
|
+
if ("TERM_PROGRAM" in env) {
|
|
312
|
+
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
313
|
+
switch (env.TERM_PROGRAM) {
|
|
314
|
+
case "iTerm.app": {
|
|
315
|
+
return version >= 3 ? 3 : 2;
|
|
316
|
+
}
|
|
317
|
+
case "Apple_Terminal": {
|
|
318
|
+
return 2;
|
|
319
|
+
}
|
|
223
320
|
}
|
|
224
|
-
});
|
|
225
|
-
if (!res.ok) {
|
|
226
|
-
const body = await readErrorBody(res);
|
|
227
|
-
throw new Error(`Region token exchange failed (${res.status}): ${body || res.statusText}`);
|
|
228
321
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
__name(getRegionToken, "getRegionToken");
|
|
232
|
-
function normalizeWorkspaces(data) {
|
|
233
|
-
const namespaces = Array.isArray(data.data) ? data.data : data.data?.namespaces;
|
|
234
|
-
return Array.isArray(namespaces) ? namespaces : [];
|
|
235
|
-
}
|
|
236
|
-
__name(normalizeWorkspaces, "normalizeWorkspaces");
|
|
237
|
-
async function listRemoteWorkspaces(region, regionalToken, deps = {}) {
|
|
238
|
-
const { fetch: fetchImpl } = withDeps(deps);
|
|
239
|
-
const res = await fetchImpl(`${region}/api/auth/namespace/list`, {
|
|
240
|
-
headers: { Authorization: regionalToken }
|
|
241
|
-
});
|
|
242
|
-
if (!res.ok) {
|
|
243
|
-
const body = await readErrorBody(res);
|
|
244
|
-
throw new Error(`List workspaces failed (${res.status}): ${body || res.statusText}`);
|
|
322
|
+
if (/-256(color)?$/i.test(env.TERM)) {
|
|
323
|
+
return 2;
|
|
245
324
|
}
|
|
246
|
-
|
|
325
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
326
|
+
return 1;
|
|
327
|
+
}
|
|
328
|
+
if ("COLORTERM" in env) {
|
|
329
|
+
return 1;
|
|
330
|
+
}
|
|
331
|
+
return min;
|
|
247
332
|
}
|
|
248
|
-
__name(
|
|
249
|
-
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
headers: {
|
|
254
|
-
Authorization: regionalToken,
|
|
255
|
-
"Content-Type": "application/json"
|
|
256
|
-
},
|
|
257
|
-
body: JSON.stringify({ ns_uid: nsUid })
|
|
333
|
+
__name(_supportsColor, "_supportsColor");
|
|
334
|
+
function createSupportsColor(stream, options = {}) {
|
|
335
|
+
const level = _supportsColor(stream, {
|
|
336
|
+
streamIsTTY: stream && stream.isTTY,
|
|
337
|
+
...options
|
|
258
338
|
});
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
339
|
+
return translateLevel(level);
|
|
340
|
+
}
|
|
341
|
+
__name(createSupportsColor, "createSupportsColor");
|
|
342
|
+
var supportsColor = {
|
|
343
|
+
stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
|
|
344
|
+
stderr: createSupportsColor({ isTTY: tty.isatty(2) })
|
|
345
|
+
};
|
|
346
|
+
var supports_color_default = supportsColor;
|
|
347
|
+
|
|
348
|
+
// node_modules/chalk/source/utilities.js
|
|
349
|
+
function stringReplaceAll(string, substring, replacer) {
|
|
350
|
+
let index = string.indexOf(substring);
|
|
351
|
+
if (index === -1) {
|
|
352
|
+
return string;
|
|
262
353
|
}
|
|
263
|
-
|
|
354
|
+
const substringLength = substring.length;
|
|
355
|
+
let endIndex = 0;
|
|
356
|
+
let returnValue = "";
|
|
357
|
+
do {
|
|
358
|
+
returnValue += string.slice(endIndex, index) + substring + replacer;
|
|
359
|
+
endIndex = index + substringLength;
|
|
360
|
+
index = string.indexOf(substring, endIndex);
|
|
361
|
+
} while (index !== -1);
|
|
362
|
+
returnValue += string.slice(endIndex);
|
|
363
|
+
return returnValue;
|
|
264
364
|
}
|
|
265
|
-
__name(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
365
|
+
__name(stringReplaceAll, "stringReplaceAll");
|
|
366
|
+
function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
367
|
+
let endIndex = 0;
|
|
368
|
+
let returnValue = "";
|
|
369
|
+
do {
|
|
370
|
+
const gotCR = string[index - 1] === "\r";
|
|
371
|
+
returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
|
|
372
|
+
endIndex = index + 1;
|
|
373
|
+
index = string.indexOf("\n", endIndex);
|
|
374
|
+
} while (index !== -1);
|
|
375
|
+
returnValue += string.slice(endIndex);
|
|
376
|
+
return returnValue;
|
|
377
|
+
}
|
|
378
|
+
__name(stringEncaseCRLFWithFirstIndex, "stringEncaseCRLFWithFirstIndex");
|
|
379
|
+
|
|
380
|
+
// node_modules/chalk/source/index.js
|
|
381
|
+
var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
|
|
382
|
+
var GENERATOR = /* @__PURE__ */ Symbol("GENERATOR");
|
|
383
|
+
var STYLER = /* @__PURE__ */ Symbol("STYLER");
|
|
384
|
+
var IS_EMPTY = /* @__PURE__ */ Symbol("IS_EMPTY");
|
|
385
|
+
var levelMapping = [
|
|
386
|
+
"ansi",
|
|
387
|
+
"ansi",
|
|
388
|
+
"ansi256",
|
|
389
|
+
"ansi16m"
|
|
390
|
+
];
|
|
391
|
+
var styles2 = /* @__PURE__ */ Object.create(null);
|
|
392
|
+
var applyOptions = /* @__PURE__ */ __name((object, options = {}) => {
|
|
393
|
+
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
|
|
394
|
+
throw new Error("The `level` option should be an integer from 0 to 3");
|
|
274
395
|
}
|
|
275
|
-
|
|
396
|
+
const colorLevel = stdoutColor ? stdoutColor.level : 0;
|
|
397
|
+
object.level = options.level === void 0 ? colorLevel : options.level;
|
|
398
|
+
}, "applyOptions");
|
|
399
|
+
var chalkFactory = /* @__PURE__ */ __name((options) => {
|
|
400
|
+
const chalk2 = /* @__PURE__ */ __name((...strings) => strings.join(" "), "chalk");
|
|
401
|
+
applyOptions(chalk2, options);
|
|
402
|
+
Object.setPrototypeOf(chalk2, createChalk.prototype);
|
|
403
|
+
return chalk2;
|
|
404
|
+
}, "chalkFactory");
|
|
405
|
+
function createChalk(options) {
|
|
406
|
+
return chalkFactory(options);
|
|
276
407
|
}
|
|
277
|
-
__name(
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
408
|
+
__name(createChalk, "createChalk");
|
|
409
|
+
Object.setPrototypeOf(createChalk.prototype, Function.prototype);
|
|
410
|
+
for (const [styleName, style] of Object.entries(ansi_styles_default)) {
|
|
411
|
+
styles2[styleName] = {
|
|
412
|
+
get() {
|
|
413
|
+
const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
|
|
414
|
+
Object.defineProperty(this, styleName, { value: builder });
|
|
415
|
+
return builder;
|
|
416
|
+
}
|
|
417
|
+
};
|
|
282
418
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
419
|
+
styles2.visible = {
|
|
420
|
+
get() {
|
|
421
|
+
const builder = createBuilder(this, this[STYLER], true);
|
|
422
|
+
Object.defineProperty(this, "visible", { value: builder });
|
|
423
|
+
return builder;
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
var getModelAnsi = /* @__PURE__ */ __name((model, level, type, ...arguments_) => {
|
|
427
|
+
if (model === "rgb") {
|
|
428
|
+
if (level === "ansi16m") {
|
|
429
|
+
return ansi_styles_default[type].ansi16m(...arguments_);
|
|
430
|
+
}
|
|
431
|
+
if (level === "ansi256") {
|
|
432
|
+
return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
|
|
433
|
+
}
|
|
434
|
+
return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
|
|
435
|
+
}
|
|
436
|
+
if (model === "hex") {
|
|
437
|
+
return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
|
|
438
|
+
}
|
|
439
|
+
return ansi_styles_default[type][model](...arguments_);
|
|
440
|
+
}, "getModelAnsi");
|
|
441
|
+
var usedModels = ["rgb", "hex", "ansi256"];
|
|
442
|
+
for (const model of usedModels) {
|
|
443
|
+
styles2[model] = {
|
|
444
|
+
get() {
|
|
445
|
+
const { level } = this;
|
|
446
|
+
return function(...arguments_) {
|
|
447
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
|
|
448
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
|
|
453
|
+
styles2[bgModel] = {
|
|
454
|
+
get() {
|
|
455
|
+
const { level } = this;
|
|
456
|
+
return function(...arguments_) {
|
|
457
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
|
|
458
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
459
|
+
};
|
|
460
|
+
}
|
|
297
461
|
};
|
|
298
462
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
expires_in: expiresIn,
|
|
310
|
-
interval = 5
|
|
311
|
-
} = deviceAuth;
|
|
312
|
-
const url = verificationUriComplete || verificationUri;
|
|
313
|
-
fullDeps.stderr.write(`
|
|
314
|
-
Please open the following URL in your browser to authorize:
|
|
315
|
-
|
|
316
|
-
${url}
|
|
317
|
-
|
|
318
|
-
Authorization code: ${userCode}
|
|
319
|
-
Expires in: ${Math.floor(expiresIn / 60)} minutes
|
|
320
|
-
|
|
321
|
-
Waiting for authorization...
|
|
322
|
-
`);
|
|
323
|
-
if (url) {
|
|
324
|
-
try {
|
|
325
|
-
fullDeps.openBrowser(url);
|
|
326
|
-
fullDeps.stderr.write("Browser opened automatically.\n");
|
|
327
|
-
} catch {
|
|
328
|
-
fullDeps.stderr.write("Could not open browser automatically. Please open the URL manually.\n");
|
|
463
|
+
var proto = Object.defineProperties(() => {
|
|
464
|
+
}, {
|
|
465
|
+
...styles2,
|
|
466
|
+
level: {
|
|
467
|
+
enumerable: true,
|
|
468
|
+
get() {
|
|
469
|
+
return this[GENERATOR].level;
|
|
470
|
+
},
|
|
471
|
+
set(level) {
|
|
472
|
+
this[GENERATOR].level = level;
|
|
329
473
|
}
|
|
330
474
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
475
|
+
});
|
|
476
|
+
var createStyler = /* @__PURE__ */ __name((open, close, parent) => {
|
|
477
|
+
let openAll;
|
|
478
|
+
let closeAll;
|
|
479
|
+
if (parent === void 0) {
|
|
480
|
+
openAll = open;
|
|
481
|
+
closeAll = close;
|
|
482
|
+
} else {
|
|
483
|
+
openAll = parent.openAll + open;
|
|
484
|
+
closeAll = close + parent.closeAll;
|
|
335
485
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
486
|
+
return {
|
|
487
|
+
open,
|
|
488
|
+
close,
|
|
489
|
+
openAll,
|
|
490
|
+
closeAll,
|
|
491
|
+
parent
|
|
492
|
+
};
|
|
493
|
+
}, "createStyler");
|
|
494
|
+
var createBuilder = /* @__PURE__ */ __name((self, _styler, _isEmpty) => {
|
|
495
|
+
const builder = /* @__PURE__ */ __name((...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" ")), "builder");
|
|
496
|
+
Object.setPrototypeOf(builder, proto);
|
|
497
|
+
builder[GENERATOR] = self;
|
|
498
|
+
builder[STYLER] = _styler;
|
|
499
|
+
builder[IS_EMPTY] = _isEmpty;
|
|
500
|
+
return builder;
|
|
501
|
+
}, "createBuilder");
|
|
502
|
+
var applyStyle = /* @__PURE__ */ __name((self, string) => {
|
|
503
|
+
if (self.level <= 0 || !string) {
|
|
504
|
+
return self[IS_EMPTY] ? "" : string;
|
|
342
505
|
}
|
|
343
|
-
|
|
344
|
-
|
|
506
|
+
let styler = self[STYLER];
|
|
507
|
+
if (styler === void 0) {
|
|
508
|
+
return string;
|
|
345
509
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
510
|
+
const { openAll, closeAll } = styler;
|
|
511
|
+
if (string.includes("\x1B")) {
|
|
512
|
+
while (styler !== void 0) {
|
|
513
|
+
string = stringReplaceAll(string, styler.close, styler.open);
|
|
514
|
+
styler = styler.parent;
|
|
515
|
+
}
|
|
352
516
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
access_token: accessToken,
|
|
357
|
-
regional_token: regionalToken,
|
|
358
|
-
authenticated_at: fullDeps.now().toISOString(),
|
|
359
|
-
auth_method: AUTH_METHOD_DEVICE_GRANT,
|
|
360
|
-
...currentWorkspace ? {
|
|
361
|
-
current_workspace: {
|
|
362
|
-
uid: currentWorkspace.uid,
|
|
363
|
-
id: currentWorkspace.id,
|
|
364
|
-
teamName: currentWorkspace.teamName
|
|
365
|
-
}
|
|
366
|
-
} : {}
|
|
367
|
-
}, fullDeps);
|
|
368
|
-
fullDeps.stderr.write("Authentication successful!\n");
|
|
369
|
-
return {
|
|
370
|
-
kubeconfig_path: fullDeps.paths.kubeconfigPath,
|
|
371
|
-
region: normalizedRegion,
|
|
372
|
-
workspace: currentWorkspace?.id || "default"
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
__name(loginWithDeviceFlow, "loginWithDeviceFlow");
|
|
376
|
-
async function listWorkspaces(deps = {}) {
|
|
377
|
-
const auth = loadAuth(deps);
|
|
378
|
-
if (!auth.regional_token) {
|
|
379
|
-
throw new Error("No regional_token found. Please run: sealos-cli login");
|
|
517
|
+
const lfIndex = string.indexOf("\n");
|
|
518
|
+
if (lfIndex !== -1) {
|
|
519
|
+
string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
|
|
380
520
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
async function switchWorkspace(target, deps = {}) {
|
|
395
|
-
if (!target) {
|
|
396
|
-
throw new Error("Usage: sealos-cli auth switch <namespace-id-or-uid>");
|
|
521
|
+
return openAll + string + closeAll;
|
|
522
|
+
}, "applyStyle");
|
|
523
|
+
Object.defineProperties(createChalk.prototype, styles2);
|
|
524
|
+
var chalk = createChalk();
|
|
525
|
+
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
526
|
+
var source_default = chalk;
|
|
527
|
+
|
|
528
|
+
// src/lib/errors.ts
|
|
529
|
+
var CliError = class extends Error {
|
|
530
|
+
constructor(message, exitCode = 1) {
|
|
531
|
+
super(message);
|
|
532
|
+
this.exitCode = exitCode;
|
|
533
|
+
this.name = "CliError";
|
|
397
534
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
throw new Error("No regional_token found. Please run: sealos-cli login");
|
|
535
|
+
exitCode;
|
|
536
|
+
static {
|
|
537
|
+
__name(this, "CliError");
|
|
402
538
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
539
|
+
};
|
|
540
|
+
var AuthError = class extends CliError {
|
|
541
|
+
static {
|
|
542
|
+
__name(this, "AuthError");
|
|
406
543
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
);
|
|
411
|
-
if (!match?.uid) {
|
|
412
|
-
const available = workspaces.map((workspace) => ` ${workspace.id || "unknown"} (${workspace.teamName || "unknown"})`).join("\n");
|
|
413
|
-
throw new Error(`No workspace matching "${target}". Available:
|
|
414
|
-
${available}`);
|
|
544
|
+
constructor(message = 'Authentication required. Please run "sealos-cli login" first.') {
|
|
545
|
+
super(message, 1);
|
|
546
|
+
this.name = "AuthError";
|
|
415
547
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if (!newToken) {
|
|
421
|
-
throw new Error("Switch response missing data.token");
|
|
548
|
+
};
|
|
549
|
+
var ConfigError = class extends CliError {
|
|
550
|
+
static {
|
|
551
|
+
__name(this, "ConfigError");
|
|
422
552
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
throw new Error("Kubeconfig response missing data.kubeconfig");
|
|
553
|
+
constructor(message) {
|
|
554
|
+
super(message, 1);
|
|
555
|
+
this.name = "ConfigError";
|
|
427
556
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
workspace: {
|
|
443
|
-
uid: match.uid,
|
|
444
|
-
id: match.id,
|
|
445
|
-
teamName: match.teamName
|
|
446
|
-
},
|
|
447
|
-
kubeconfig_path: fullDeps.paths.kubeconfigPath
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
__name(switchWorkspace, "switchWorkspace");
|
|
451
|
-
|
|
452
|
-
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
453
|
-
var ANSI_BACKGROUND_OFFSET = 10;
|
|
454
|
-
var wrapAnsi16 = /* @__PURE__ */ __name((offset = 0) => (code) => `\x1B[${code + offset}m`, "wrapAnsi16");
|
|
455
|
-
var wrapAnsi256 = /* @__PURE__ */ __name((offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`, "wrapAnsi256");
|
|
456
|
-
var wrapAnsi16m = /* @__PURE__ */ __name((offset = 0) => (red2, green2, blue2) => `\x1B[${38 + offset};2;${red2};${green2};${blue2}m`, "wrapAnsi16m");
|
|
457
|
-
var styles = {
|
|
458
|
-
modifier: {
|
|
459
|
-
reset: [0, 0],
|
|
460
|
-
// 21 isn't widely supported and 22 does the same thing
|
|
461
|
-
bold: [1, 22],
|
|
462
|
-
dim: [2, 22],
|
|
463
|
-
italic: [3, 23],
|
|
464
|
-
underline: [4, 24],
|
|
465
|
-
overline: [53, 55],
|
|
466
|
-
inverse: [7, 27],
|
|
467
|
-
hidden: [8, 28],
|
|
468
|
-
strikethrough: [9, 29]
|
|
469
|
-
},
|
|
470
|
-
color: {
|
|
471
|
-
black: [30, 39],
|
|
472
|
-
red: [31, 39],
|
|
473
|
-
green: [32, 39],
|
|
474
|
-
yellow: [33, 39],
|
|
475
|
-
blue: [34, 39],
|
|
476
|
-
magenta: [35, 39],
|
|
477
|
-
cyan: [36, 39],
|
|
478
|
-
white: [37, 39],
|
|
479
|
-
// Bright color
|
|
480
|
-
blackBright: [90, 39],
|
|
481
|
-
gray: [90, 39],
|
|
482
|
-
// Alias of `blackBright`
|
|
483
|
-
grey: [90, 39],
|
|
484
|
-
// Alias of `blackBright`
|
|
485
|
-
redBright: [91, 39],
|
|
486
|
-
greenBright: [92, 39],
|
|
487
|
-
yellowBright: [93, 39],
|
|
488
|
-
blueBright: [94, 39],
|
|
489
|
-
magentaBright: [95, 39],
|
|
490
|
-
cyanBright: [96, 39],
|
|
491
|
-
whiteBright: [97, 39]
|
|
492
|
-
},
|
|
493
|
-
bgColor: {
|
|
494
|
-
bgBlack: [40, 49],
|
|
495
|
-
bgRed: [41, 49],
|
|
496
|
-
bgGreen: [42, 49],
|
|
497
|
-
bgYellow: [43, 49],
|
|
498
|
-
bgBlue: [44, 49],
|
|
499
|
-
bgMagenta: [45, 49],
|
|
500
|
-
bgCyan: [46, 49],
|
|
501
|
-
bgWhite: [47, 49],
|
|
502
|
-
// Bright color
|
|
503
|
-
bgBlackBright: [100, 49],
|
|
504
|
-
bgGray: [100, 49],
|
|
505
|
-
// Alias of `bgBlackBright`
|
|
506
|
-
bgGrey: [100, 49],
|
|
507
|
-
// Alias of `bgBlackBright`
|
|
508
|
-
bgRedBright: [101, 49],
|
|
509
|
-
bgGreenBright: [102, 49],
|
|
510
|
-
bgYellowBright: [103, 49],
|
|
511
|
-
bgBlueBright: [104, 49],
|
|
512
|
-
bgMagentaBright: [105, 49],
|
|
513
|
-
bgCyanBright: [106, 49],
|
|
514
|
-
bgWhiteBright: [107, 49]
|
|
557
|
+
};
|
|
558
|
+
var ApiError = class extends CliError {
|
|
559
|
+
constructor(message, statusCode, code, details) {
|
|
560
|
+
super(message, 1);
|
|
561
|
+
this.statusCode = statusCode;
|
|
562
|
+
this.code = code;
|
|
563
|
+
this.details = details;
|
|
564
|
+
this.name = "ApiError";
|
|
565
|
+
}
|
|
566
|
+
statusCode;
|
|
567
|
+
code;
|
|
568
|
+
details;
|
|
569
|
+
static {
|
|
570
|
+
__name(this, "ApiError");
|
|
515
571
|
}
|
|
516
572
|
};
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
function assembleStyles() {
|
|
522
|
-
const codes = /* @__PURE__ */ new Map();
|
|
523
|
-
for (const [groupName, group] of Object.entries(styles)) {
|
|
524
|
-
for (const [styleName, style] of Object.entries(group)) {
|
|
525
|
-
styles[styleName] = {
|
|
526
|
-
open: `\x1B[${style[0]}m`,
|
|
527
|
-
close: `\x1B[${style[1]}m`
|
|
528
|
-
};
|
|
529
|
-
group[styleName] = styles[styleName];
|
|
530
|
-
codes.set(style[0], style[1]);
|
|
531
|
-
}
|
|
532
|
-
Object.defineProperty(styles, groupName, {
|
|
533
|
-
value: group,
|
|
534
|
-
enumerable: false
|
|
535
|
-
});
|
|
573
|
+
function mapApiError(status, body) {
|
|
574
|
+
const message = body?.error?.message || `API request failed with status ${status}`;
|
|
575
|
+
if (status === 401) {
|
|
576
|
+
return new AuthError(message);
|
|
536
577
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
|
|
548
|
-
styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
|
549
|
-
Object.defineProperties(styles, {
|
|
550
|
-
rgbToAnsi256: {
|
|
551
|
-
value(red2, green2, blue2) {
|
|
552
|
-
if (red2 === green2 && green2 === blue2) {
|
|
553
|
-
if (red2 < 8) {
|
|
554
|
-
return 16;
|
|
555
|
-
}
|
|
556
|
-
if (red2 > 248) {
|
|
557
|
-
return 231;
|
|
558
|
-
}
|
|
559
|
-
return Math.round((red2 - 8) / 247 * 24) + 232;
|
|
560
|
-
}
|
|
561
|
-
return 16 + 36 * Math.round(red2 / 255 * 5) + 6 * Math.round(green2 / 255 * 5) + Math.round(blue2 / 255 * 5);
|
|
562
|
-
},
|
|
563
|
-
enumerable: false
|
|
564
|
-
},
|
|
565
|
-
hexToRgb: {
|
|
566
|
-
value(hex) {
|
|
567
|
-
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
|
|
568
|
-
if (!matches) {
|
|
569
|
-
return [0, 0, 0];
|
|
570
|
-
}
|
|
571
|
-
let [colorString] = matches;
|
|
572
|
-
if (colorString.length === 3) {
|
|
573
|
-
colorString = [...colorString].map((character) => character + character).join("");
|
|
574
|
-
}
|
|
575
|
-
const integer = Number.parseInt(colorString, 16);
|
|
576
|
-
return [
|
|
577
|
-
/* eslint-disable no-bitwise */
|
|
578
|
-
integer >> 16 & 255,
|
|
579
|
-
integer >> 8 & 255,
|
|
580
|
-
integer & 255
|
|
581
|
-
/* eslint-enable no-bitwise */
|
|
582
|
-
];
|
|
583
|
-
},
|
|
584
|
-
enumerable: false
|
|
585
|
-
},
|
|
586
|
-
hexToAnsi256: {
|
|
587
|
-
value: /* @__PURE__ */ __name((hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)), "value"),
|
|
588
|
-
enumerable: false
|
|
589
|
-
},
|
|
590
|
-
ansi256ToAnsi: {
|
|
591
|
-
value(code) {
|
|
592
|
-
if (code < 8) {
|
|
593
|
-
return 30 + code;
|
|
594
|
-
}
|
|
595
|
-
if (code < 16) {
|
|
596
|
-
return 90 + (code - 8);
|
|
597
|
-
}
|
|
598
|
-
let red2;
|
|
599
|
-
let green2;
|
|
600
|
-
let blue2;
|
|
601
|
-
if (code >= 232) {
|
|
602
|
-
red2 = ((code - 232) * 10 + 8) / 255;
|
|
603
|
-
green2 = red2;
|
|
604
|
-
blue2 = red2;
|
|
605
|
-
} else {
|
|
606
|
-
code -= 16;
|
|
607
|
-
const remainder = code % 36;
|
|
608
|
-
red2 = Math.floor(code / 36) / 5;
|
|
609
|
-
green2 = Math.floor(remainder / 6) / 5;
|
|
610
|
-
blue2 = remainder % 6 / 5;
|
|
611
|
-
}
|
|
612
|
-
const value = Math.max(red2, green2, blue2) * 2;
|
|
613
|
-
if (value === 0) {
|
|
614
|
-
return 30;
|
|
615
|
-
}
|
|
616
|
-
let result = 30 + (Math.round(blue2) << 2 | Math.round(green2) << 1 | Math.round(red2));
|
|
617
|
-
if (value === 2) {
|
|
618
|
-
result += 60;
|
|
578
|
+
return new ApiError(message, status, body?.error?.code, body?.error?.details);
|
|
579
|
+
}
|
|
580
|
+
__name(mapApiError, "mapApiError");
|
|
581
|
+
function handleError(error2) {
|
|
582
|
+
if (error2 instanceof ApiError) {
|
|
583
|
+
console.error(source_default.red("Error:"), error2.message);
|
|
584
|
+
if (error2.details) {
|
|
585
|
+
if (Array.isArray(error2.details)) {
|
|
586
|
+
for (const d of error2.details) {
|
|
587
|
+
console.error(source_default.yellow(` ${d.field}:`), d.message);
|
|
619
588
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
},
|
|
624
|
-
rgbToAnsi: {
|
|
625
|
-
value: /* @__PURE__ */ __name((red2, green2, blue2) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red2, green2, blue2)), "value"),
|
|
626
|
-
enumerable: false
|
|
627
|
-
},
|
|
628
|
-
hexToAnsi: {
|
|
629
|
-
value: /* @__PURE__ */ __name((hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)), "value"),
|
|
630
|
-
enumerable: false
|
|
589
|
+
} else {
|
|
590
|
+
console.error(source_default.yellow(" Details:"), error2.details);
|
|
591
|
+
}
|
|
631
592
|
}
|
|
632
|
-
|
|
633
|
-
|
|
593
|
+
process.exit(error2.exitCode);
|
|
594
|
+
}
|
|
595
|
+
if (error2 instanceof CliError) {
|
|
596
|
+
console.error(source_default.red("Error:"), error2.message);
|
|
597
|
+
process.exit(error2.exitCode);
|
|
598
|
+
}
|
|
599
|
+
if (error2 instanceof Error) {
|
|
600
|
+
console.error(source_default.red("Error:"), error2.message);
|
|
601
|
+
if (process.env.DEBUG) {
|
|
602
|
+
console.error(error2.stack);
|
|
603
|
+
}
|
|
604
|
+
process.exit(1);
|
|
605
|
+
}
|
|
606
|
+
console.error(source_default.red("Error:"), "An unknown error occurred");
|
|
607
|
+
process.exit(1);
|
|
634
608
|
}
|
|
635
|
-
__name(
|
|
636
|
-
var ansiStyles = assembleStyles();
|
|
637
|
-
var ansi_styles_default = ansiStyles;
|
|
609
|
+
__name(handleError, "handleError");
|
|
638
610
|
|
|
639
|
-
//
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
611
|
+
// src/lib/auth.ts
|
|
612
|
+
var SEALOS_AUTH_CLIENT_ID = "af993c98-d19d-4bdc-b338-79b80dc4f8bf";
|
|
613
|
+
var DEFAULT_SEALOS_REGION = "https://usw-1.sealos.io";
|
|
614
|
+
var AUTH_METHOD_DEVICE_GRANT = "oauth2_device_grant";
|
|
615
|
+
var AUTH_METHOD_TOKEN = "token";
|
|
616
|
+
var DEVICE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
617
|
+
function getAuthPaths(sealosDir = join(homedir(), ".sealos")) {
|
|
618
|
+
return {
|
|
619
|
+
sealosDir,
|
|
620
|
+
authPath: join(sealosDir, "auth.json"),
|
|
621
|
+
kubeconfigPath: join(sealosDir, "kubeconfig")
|
|
622
|
+
};
|
|
648
623
|
}
|
|
649
|
-
__name(
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
624
|
+
__name(getAuthPaths, "getAuthPaths");
|
|
625
|
+
function normalizeRegion(region) {
|
|
626
|
+
return (region || process.env.SEALOS_REGION || DEFAULT_SEALOS_REGION).replace(/\/+$/, "");
|
|
627
|
+
}
|
|
628
|
+
__name(normalizeRegion, "normalizeRegion");
|
|
629
|
+
function createDefaultAuthDependencies() {
|
|
630
|
+
return {
|
|
631
|
+
fetch,
|
|
632
|
+
sleep: /* @__PURE__ */ __name(async (ms) => await new Promise((resolve) => setTimeout(resolve, ms)), "sleep"),
|
|
633
|
+
openBrowser,
|
|
634
|
+
now: /* @__PURE__ */ __name(() => /* @__PURE__ */ new Date(), "now"),
|
|
635
|
+
paths: getAuthPaths(),
|
|
636
|
+
stderr: process.stderr
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
__name(createDefaultAuthDependencies, "createDefaultAuthDependencies");
|
|
640
|
+
function withDeps(deps = {}) {
|
|
641
|
+
return {
|
|
642
|
+
...createDefaultAuthDependencies(),
|
|
643
|
+
...deps
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
__name(withDeps, "withDeps");
|
|
647
|
+
function ensureSealosDir(paths) {
|
|
648
|
+
mkdirSync(paths.sealosDir, { recursive: true });
|
|
649
|
+
}
|
|
650
|
+
__name(ensureSealosDir, "ensureSealosDir");
|
|
651
|
+
function saveAuth(auth, deps = {}) {
|
|
652
|
+
const { paths } = withDeps(deps);
|
|
653
|
+
ensureSealosDir(paths);
|
|
654
|
+
writeFileSync(paths.authPath, JSON.stringify(auth, null, 2), { mode: 384 });
|
|
655
|
+
}
|
|
656
|
+
__name(saveAuth, "saveAuth");
|
|
657
|
+
function loadAuth(deps = {}) {
|
|
658
|
+
const { paths } = withDeps(deps);
|
|
659
|
+
if (!existsSync(paths.authPath)) {
|
|
660
|
+
throw new Error("Not authenticated. Please run: sealos-cli login");
|
|
661
|
+
}
|
|
662
|
+
return JSON.parse(readFileSync(paths.authPath, "utf-8"));
|
|
663
|
+
}
|
|
664
|
+
__name(loadAuth, "loadAuth");
|
|
665
|
+
function getKubeconfigContent(deps = {}) {
|
|
666
|
+
const { paths } = withDeps(deps);
|
|
667
|
+
try {
|
|
668
|
+
return readFileSync(paths.kubeconfigPath, "utf-8");
|
|
669
|
+
} catch {
|
|
670
|
+
return null;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
__name(getKubeconfigContent, "getKubeconfigContent");
|
|
674
|
+
function getAuthHeaders(deps = {}) {
|
|
675
|
+
const kubeconfig = getKubeconfigContent(deps);
|
|
676
|
+
return kubeconfig ? { Authorization: encodeURIComponent(kubeconfig) } : null;
|
|
677
|
+
}
|
|
678
|
+
__name(getAuthHeaders, "getAuthHeaders");
|
|
679
|
+
function requireAuth(deps = {}) {
|
|
680
|
+
const headers = getAuthHeaders(deps);
|
|
681
|
+
if (!headers) {
|
|
682
|
+
throw new Error('Authentication required. Please run "sealos-cli login" first.');
|
|
683
|
+
}
|
|
684
|
+
return headers;
|
|
685
|
+
}
|
|
686
|
+
__name(requireAuth, "requireAuth");
|
|
687
|
+
function saveKubeconfig(kubeconfig, deps = {}) {
|
|
688
|
+
const { paths } = withDeps(deps);
|
|
689
|
+
ensureSealosDir(paths);
|
|
690
|
+
writeFileSync(paths.kubeconfigPath, kubeconfig, { mode: 384 });
|
|
691
|
+
}
|
|
692
|
+
__name(saveKubeconfig, "saveKubeconfig");
|
|
693
|
+
function clearAuth(deps = {}) {
|
|
694
|
+
const { paths } = withDeps(deps);
|
|
695
|
+
rmSync(paths.authPath, { force: true });
|
|
696
|
+
rmSync(paths.kubeconfigPath, { force: true });
|
|
656
697
|
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
|
|
698
|
+
__name(clearAuth, "clearAuth");
|
|
699
|
+
function checkAuth(deps = {}) {
|
|
700
|
+
const { paths } = withDeps(deps);
|
|
701
|
+
if (!existsSync(paths.kubeconfigPath)) {
|
|
702
|
+
return { authenticated: false };
|
|
703
|
+
}
|
|
704
|
+
try {
|
|
705
|
+
const kubeconfig = readFileSync(paths.kubeconfigPath, "utf-8");
|
|
706
|
+
if (!kubeconfig.includes("server:") || !kubeconfig.includes("token:") && !kubeconfig.includes("client-certificate")) {
|
|
707
|
+
return { authenticated: false };
|
|
664
708
|
}
|
|
665
|
-
|
|
709
|
+
const auth = existsSync(paths.authPath) ? JSON.parse(readFileSync(paths.authPath, "utf-8")) : {};
|
|
710
|
+
return {
|
|
711
|
+
authenticated: true,
|
|
712
|
+
kubeconfig_path: paths.kubeconfigPath,
|
|
713
|
+
region: auth.region || "unknown",
|
|
714
|
+
workspace: auth.current_workspace?.id || "unknown"
|
|
715
|
+
};
|
|
716
|
+
} catch {
|
|
717
|
+
return { authenticated: false };
|
|
666
718
|
}
|
|
667
719
|
}
|
|
668
|
-
__name(
|
|
669
|
-
function
|
|
670
|
-
|
|
671
|
-
|
|
720
|
+
__name(checkAuth, "checkAuth");
|
|
721
|
+
function getAuthInfo(deps = {}) {
|
|
722
|
+
const { paths } = withDeps(deps);
|
|
723
|
+
const status = checkAuth(deps);
|
|
724
|
+
if (!status.authenticated) {
|
|
725
|
+
return { authenticated: false };
|
|
672
726
|
}
|
|
727
|
+
const auth = existsSync(paths.authPath) ? JSON.parse(readFileSync(paths.authPath, "utf-8")) : {};
|
|
673
728
|
return {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
729
|
+
...status,
|
|
730
|
+
auth_method: auth.auth_method || "unknown",
|
|
731
|
+
authenticated_at: auth.authenticated_at || "unknown",
|
|
732
|
+
current_workspace: auth.current_workspace || null
|
|
678
733
|
};
|
|
679
734
|
}
|
|
680
|
-
__name(
|
|
681
|
-
function
|
|
682
|
-
const
|
|
683
|
-
if (
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
if (forceColor === 0) {
|
|
688
|
-
return 0;
|
|
689
|
-
}
|
|
690
|
-
if (sniffFlags) {
|
|
691
|
-
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
692
|
-
return 3;
|
|
693
|
-
}
|
|
694
|
-
if (hasFlag("color=256")) {
|
|
695
|
-
return 2;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
if ("TF_BUILD" in env && "AGENT_NAME" in env) {
|
|
699
|
-
return 1;
|
|
700
|
-
}
|
|
701
|
-
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
702
|
-
return 0;
|
|
703
|
-
}
|
|
704
|
-
const min = forceColor || 0;
|
|
705
|
-
if (env.TERM === "dumb") {
|
|
706
|
-
return min;
|
|
707
|
-
}
|
|
708
|
-
if (process2.platform === "win32") {
|
|
709
|
-
const osRelease = os.release().split(".");
|
|
710
|
-
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
711
|
-
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
712
|
-
}
|
|
713
|
-
return 1;
|
|
714
|
-
}
|
|
715
|
-
if ("CI" in env) {
|
|
716
|
-
if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => key in env)) {
|
|
717
|
-
return 3;
|
|
718
|
-
}
|
|
719
|
-
if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
|
|
720
|
-
return 1;
|
|
721
|
-
}
|
|
722
|
-
return min;
|
|
723
|
-
}
|
|
724
|
-
if ("TEAMCITY_VERSION" in env) {
|
|
725
|
-
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
726
|
-
}
|
|
727
|
-
if (env.COLORTERM === "truecolor") {
|
|
728
|
-
return 3;
|
|
729
|
-
}
|
|
730
|
-
if (env.TERM === "xterm-kitty") {
|
|
731
|
-
return 3;
|
|
732
|
-
}
|
|
733
|
-
if (env.TERM === "xterm-ghostty") {
|
|
734
|
-
return 3;
|
|
735
|
-
}
|
|
736
|
-
if (env.TERM === "wezterm") {
|
|
737
|
-
return 3;
|
|
738
|
-
}
|
|
739
|
-
if ("TERM_PROGRAM" in env) {
|
|
740
|
-
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
741
|
-
switch (env.TERM_PROGRAM) {
|
|
742
|
-
case "iTerm.app": {
|
|
743
|
-
return version >= 3 ? 3 : 2;
|
|
744
|
-
}
|
|
745
|
-
case "Apple_Terminal": {
|
|
746
|
-
return 2;
|
|
747
|
-
}
|
|
735
|
+
__name(getAuthInfo, "getAuthInfo");
|
|
736
|
+
async function parseResponse(res) {
|
|
737
|
+
const body = await res.json();
|
|
738
|
+
if (body && typeof body === "object" && typeof body.code === "number" && ![0, 200].includes(body.code)) {
|
|
739
|
+
const message = body.message || `Sealos API request failed with code ${body.code}`;
|
|
740
|
+
if (body.code === 401) {
|
|
741
|
+
throw new AuthError(`Authentication expired. Please run "sealos-cli login" again. (${message})`);
|
|
748
742
|
}
|
|
743
|
+
throw new Error(message);
|
|
749
744
|
}
|
|
750
|
-
|
|
751
|
-
return 2;
|
|
752
|
-
}
|
|
753
|
-
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
754
|
-
return 1;
|
|
755
|
-
}
|
|
756
|
-
if ("COLORTERM" in env) {
|
|
757
|
-
return 1;
|
|
758
|
-
}
|
|
759
|
-
return min;
|
|
745
|
+
return body;
|
|
760
746
|
}
|
|
761
|
-
__name(
|
|
762
|
-
function
|
|
763
|
-
|
|
764
|
-
streamIsTTY: stream && stream.isTTY,
|
|
765
|
-
...options
|
|
766
|
-
});
|
|
767
|
-
return translateLevel(level);
|
|
747
|
+
__name(parseResponse, "parseResponse");
|
|
748
|
+
async function readErrorBody(res) {
|
|
749
|
+
return await res.text().catch(() => "");
|
|
768
750
|
}
|
|
769
|
-
__name(
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
751
|
+
__name(readErrorBody, "readErrorBody");
|
|
752
|
+
async function requestDeviceAuthorization(region, deps = {}) {
|
|
753
|
+
const { fetch: fetchImpl } = withDeps(deps);
|
|
754
|
+
const res = await fetchImpl(`${region}/api/auth/oauth2/device`, {
|
|
755
|
+
method: "POST",
|
|
756
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
757
|
+
body: new URLSearchParams({
|
|
758
|
+
client_id: SEALOS_AUTH_CLIENT_ID,
|
|
759
|
+
grant_type: DEVICE_GRANT_TYPE
|
|
760
|
+
})
|
|
761
|
+
});
|
|
762
|
+
if (!res.ok) {
|
|
763
|
+
const body = await readErrorBody(res);
|
|
764
|
+
throw new Error(`Device authorization request failed (${res.status}): ${body || res.statusText}`);
|
|
781
765
|
}
|
|
782
|
-
|
|
783
|
-
let endIndex = 0;
|
|
784
|
-
let returnValue = "";
|
|
785
|
-
do {
|
|
786
|
-
returnValue += string.slice(endIndex, index) + substring + replacer;
|
|
787
|
-
endIndex = index + substringLength;
|
|
788
|
-
index = string.indexOf(substring, endIndex);
|
|
789
|
-
} while (index !== -1);
|
|
790
|
-
returnValue += string.slice(endIndex);
|
|
791
|
-
return returnValue;
|
|
792
|
-
}
|
|
793
|
-
__name(stringReplaceAll, "stringReplaceAll");
|
|
794
|
-
function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
795
|
-
let endIndex = 0;
|
|
796
|
-
let returnValue = "";
|
|
797
|
-
do {
|
|
798
|
-
const gotCR = string[index - 1] === "\r";
|
|
799
|
-
returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
|
|
800
|
-
endIndex = index + 1;
|
|
801
|
-
index = string.indexOf("\n", endIndex);
|
|
802
|
-
} while (index !== -1);
|
|
803
|
-
returnValue += string.slice(endIndex);
|
|
804
|
-
return returnValue;
|
|
766
|
+
return await parseResponse(res);
|
|
805
767
|
}
|
|
806
|
-
__name(
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
|
|
768
|
+
__name(requestDeviceAuthorization, "requestDeviceAuthorization");
|
|
769
|
+
async function pollForToken(region, deviceCode, interval, expiresIn, deps = {}) {
|
|
770
|
+
const { fetch: fetchImpl, sleep, now, stderr } = withDeps(deps);
|
|
771
|
+
const maxWait = Math.min(expiresIn, 600) * 1e3;
|
|
772
|
+
const deadline = now().getTime() + maxWait;
|
|
773
|
+
let pollInterval = interval * 1e3;
|
|
774
|
+
let lastLoggedMinute = -1;
|
|
775
|
+
while (now().getTime() < deadline) {
|
|
776
|
+
await sleep(pollInterval);
|
|
777
|
+
const remaining = Math.ceil((deadline - now().getTime()) / 6e4);
|
|
778
|
+
if (remaining !== lastLoggedMinute && remaining > 0) {
|
|
779
|
+
lastLoggedMinute = remaining;
|
|
780
|
+
stderr.write(` Waiting for authorization... (${remaining} min remaining)
|
|
781
|
+
`);
|
|
782
|
+
}
|
|
783
|
+
const res = await fetchImpl(`${region}/api/auth/oauth2/token`, {
|
|
784
|
+
method: "POST",
|
|
785
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
786
|
+
body: new URLSearchParams({
|
|
787
|
+
client_id: SEALOS_AUTH_CLIENT_ID,
|
|
788
|
+
grant_type: DEVICE_GRANT_TYPE,
|
|
789
|
+
device_code: deviceCode
|
|
790
|
+
})
|
|
791
|
+
});
|
|
792
|
+
if (res.ok) {
|
|
793
|
+
return await parseResponse(res);
|
|
794
|
+
}
|
|
795
|
+
const body = await res.json().catch(() => ({}));
|
|
796
|
+
switch (body.error) {
|
|
797
|
+
case "authorization_pending":
|
|
798
|
+
break;
|
|
799
|
+
case "slow_down":
|
|
800
|
+
pollInterval += 5e3;
|
|
801
|
+
break;
|
|
802
|
+
case "access_denied":
|
|
803
|
+
throw new Error("Authorization denied by user");
|
|
804
|
+
case "expired_token":
|
|
805
|
+
throw new Error("Device code expired. Please run login again.");
|
|
806
|
+
default:
|
|
807
|
+
throw new Error(`Token request failed: ${body.error || res.statusText}`);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
throw new Error("Authorization timed out (10 minutes). Please run login again.");
|
|
835
811
|
}
|
|
836
|
-
__name(
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
812
|
+
__name(pollForToken, "pollForToken");
|
|
813
|
+
async function getRegionToken(region, globalToken, deps = {}) {
|
|
814
|
+
const { fetch: fetchImpl } = withDeps(deps);
|
|
815
|
+
const res = await fetchImpl(`${region}/api/auth/regionToken`, {
|
|
816
|
+
method: "POST",
|
|
817
|
+
headers: {
|
|
818
|
+
Authorization: globalToken,
|
|
819
|
+
"Content-Type": "application/json"
|
|
844
820
|
}
|
|
845
|
-
};
|
|
821
|
+
});
|
|
822
|
+
if (!res.ok) {
|
|
823
|
+
const body = await readErrorBody(res);
|
|
824
|
+
throw new Error(`Region token exchange failed (${res.status}): ${body || res.statusText}`);
|
|
825
|
+
}
|
|
826
|
+
return await parseResponse(res);
|
|
846
827
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
828
|
+
__name(getRegionToken, "getRegionToken");
|
|
829
|
+
function normalizeWorkspaces(data) {
|
|
830
|
+
const namespaces = Array.isArray(data.data) ? data.data : data.data?.namespaces;
|
|
831
|
+
return Array.isArray(namespaces) ? namespaces : [];
|
|
832
|
+
}
|
|
833
|
+
__name(normalizeWorkspaces, "normalizeWorkspaces");
|
|
834
|
+
async function listRemoteWorkspaces(region, regionalToken, deps = {}) {
|
|
835
|
+
const { fetch: fetchImpl } = withDeps(deps);
|
|
836
|
+
const res = await fetchImpl(`${region}/api/auth/namespace/list`, {
|
|
837
|
+
headers: { Authorization: regionalToken }
|
|
838
|
+
});
|
|
839
|
+
if (!res.ok) {
|
|
840
|
+
const body = await readErrorBody(res);
|
|
841
|
+
throw new Error(`List workspaces failed (${res.status}): ${body || res.statusText}`);
|
|
852
842
|
}
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
843
|
+
return normalizeWorkspaces(await parseResponse(res));
|
|
844
|
+
}
|
|
845
|
+
__name(listRemoteWorkspaces, "listRemoteWorkspaces");
|
|
846
|
+
async function switchRemoteWorkspace(region, regionalToken, nsUid, deps = {}) {
|
|
847
|
+
const { fetch: fetchImpl } = withDeps(deps);
|
|
848
|
+
const res = await fetchImpl(`${region}/api/auth/namespace/switch`, {
|
|
849
|
+
method: "POST",
|
|
850
|
+
headers: {
|
|
851
|
+
Authorization: regionalToken,
|
|
852
|
+
"Content-Type": "application/json"
|
|
853
|
+
},
|
|
854
|
+
body: JSON.stringify({ ns_uid: nsUid })
|
|
855
|
+
});
|
|
856
|
+
if (!res.ok) {
|
|
857
|
+
const body = await readErrorBody(res);
|
|
858
|
+
throw new Error(`Switch workspace failed (${res.status}): ${body || res.statusText}`);
|
|
863
859
|
}
|
|
864
|
-
|
|
865
|
-
|
|
860
|
+
return await parseResponse(res);
|
|
861
|
+
}
|
|
862
|
+
__name(switchRemoteWorkspace, "switchRemoteWorkspace");
|
|
863
|
+
async function getKubeconfig(region, regionalToken, deps = {}) {
|
|
864
|
+
const { fetch: fetchImpl } = withDeps(deps);
|
|
865
|
+
const res = await fetchImpl(`${region}/api/auth/getKubeconfig`, {
|
|
866
|
+
headers: { Authorization: regionalToken }
|
|
867
|
+
});
|
|
868
|
+
if (!res.ok) {
|
|
869
|
+
const body = await readErrorBody(res);
|
|
870
|
+
throw new Error(`Get kubeconfig failed (${res.status}): ${body || res.statusText}`);
|
|
866
871
|
}
|
|
867
|
-
return
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
872
|
+
return await parseResponse(res);
|
|
873
|
+
}
|
|
874
|
+
__name(getKubeconfig, "getKubeconfig");
|
|
875
|
+
function openBrowser(url) {
|
|
876
|
+
const command = platform() === "darwin" ? "open" : platform() === "win32" ? "cmd" : "xdg-open";
|
|
877
|
+
const args = platform() === "win32" ? ["/c", "start", "", url] : [url];
|
|
878
|
+
execFileSync(command, args, { stdio: "ignore" });
|
|
879
|
+
}
|
|
880
|
+
__name(openBrowser, "openBrowser");
|
|
881
|
+
async function loginWithToken(region, token, deps = {}) {
|
|
882
|
+
const { now } = withDeps(deps);
|
|
883
|
+
const normalizedRegion = normalizeRegion(region);
|
|
884
|
+
saveAuth({
|
|
885
|
+
region: normalizedRegion,
|
|
886
|
+
regional_token: token,
|
|
887
|
+
authenticated_at: now().toISOString(),
|
|
888
|
+
auth_method: AUTH_METHOD_TOKEN
|
|
889
|
+
}, deps);
|
|
890
|
+
return {
|
|
891
|
+
region: normalizedRegion,
|
|
892
|
+
workspace: "unknown",
|
|
893
|
+
limited: true
|
|
889
894
|
};
|
|
890
895
|
}
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
896
|
+
__name(loginWithToken, "loginWithToken");
|
|
897
|
+
async function loginWithDeviceFlow(region, deps = {}) {
|
|
898
|
+
const fullDeps = withDeps(deps);
|
|
899
|
+
const normalizedRegion = normalizeRegion(region);
|
|
900
|
+
const deviceAuth = await requestDeviceAuthorization(normalizedRegion, fullDeps);
|
|
901
|
+
const {
|
|
902
|
+
device_code: deviceCode,
|
|
903
|
+
user_code: userCode,
|
|
904
|
+
verification_uri: verificationUri,
|
|
905
|
+
verification_uri_complete: verificationUriComplete,
|
|
906
|
+
expires_in: expiresIn,
|
|
907
|
+
interval = 5
|
|
908
|
+
} = deviceAuth;
|
|
909
|
+
const url = verificationUriComplete || verificationUri;
|
|
910
|
+
fullDeps.stderr.write(`
|
|
911
|
+
Please open the following URL in your browser to authorize:
|
|
912
|
+
|
|
913
|
+
${url}
|
|
914
|
+
|
|
915
|
+
Authorization code: ${userCode}
|
|
916
|
+
Expires in: ${Math.floor(expiresIn / 60)} minutes
|
|
917
|
+
|
|
918
|
+
Waiting for authorization...
|
|
919
|
+
`);
|
|
920
|
+
if (url) {
|
|
921
|
+
try {
|
|
922
|
+
fullDeps.openBrowser(url);
|
|
923
|
+
fullDeps.stderr.write("Browser opened automatically.\n");
|
|
924
|
+
} catch {
|
|
925
|
+
fullDeps.stderr.write("Could not open browser automatically. Please open the URL manually.\n");
|
|
901
926
|
}
|
|
902
927
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
928
|
+
const tokenResponse = await pollForToken(normalizedRegion, deviceCode, interval, expiresIn, fullDeps);
|
|
929
|
+
const accessToken = tokenResponse.access_token;
|
|
930
|
+
if (!accessToken) {
|
|
931
|
+
throw new Error("Token response missing access_token");
|
|
932
|
+
}
|
|
933
|
+
fullDeps.stderr.write("Authorization received. Exchanging for regional token...\n");
|
|
934
|
+
const regionData = await getRegionToken(normalizedRegion, accessToken, fullDeps);
|
|
935
|
+
const regionalToken = regionData.data?.token;
|
|
936
|
+
const kubeconfig = regionData.data?.kubeconfig;
|
|
937
|
+
if (!regionalToken) {
|
|
938
|
+
throw new Error("Region token response missing data.token field");
|
|
939
|
+
}
|
|
940
|
+
if (!kubeconfig) {
|
|
941
|
+
throw new Error("Region token response missing data.kubeconfig field");
|
|
942
|
+
}
|
|
943
|
+
let currentWorkspace;
|
|
944
|
+
try {
|
|
945
|
+
const workspaces = await listRemoteWorkspaces(normalizedRegion, regionalToken, fullDeps);
|
|
946
|
+
currentWorkspace = workspaces.find((workspace) => workspace.nstype === "private") || workspaces[0];
|
|
947
|
+
} catch {
|
|
948
|
+
currentWorkspace = void 0;
|
|
913
949
|
}
|
|
950
|
+
saveKubeconfig(kubeconfig, fullDeps);
|
|
951
|
+
saveAuth({
|
|
952
|
+
region: normalizedRegion,
|
|
953
|
+
access_token: accessToken,
|
|
954
|
+
regional_token: regionalToken,
|
|
955
|
+
authenticated_at: fullDeps.now().toISOString(),
|
|
956
|
+
auth_method: AUTH_METHOD_DEVICE_GRANT,
|
|
957
|
+
...currentWorkspace ? {
|
|
958
|
+
current_workspace: {
|
|
959
|
+
uid: currentWorkspace.uid,
|
|
960
|
+
id: currentWorkspace.id,
|
|
961
|
+
teamName: currentWorkspace.teamName
|
|
962
|
+
}
|
|
963
|
+
} : {}
|
|
964
|
+
}, fullDeps);
|
|
965
|
+
fullDeps.stderr.write("Authentication successful!\n");
|
|
914
966
|
return {
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
closeAll,
|
|
919
|
-
parent
|
|
967
|
+
kubeconfig_path: fullDeps.paths.kubeconfigPath,
|
|
968
|
+
region: normalizedRegion,
|
|
969
|
+
workspace: currentWorkspace?.id || "default"
|
|
920
970
|
};
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
971
|
+
}
|
|
972
|
+
__name(loginWithDeviceFlow, "loginWithDeviceFlow");
|
|
973
|
+
async function listWorkspaces(deps = {}) {
|
|
974
|
+
const auth = loadAuth(deps);
|
|
975
|
+
if (!auth.regional_token) {
|
|
976
|
+
throw new Error("No regional_token found. Please run: sealos-cli login");
|
|
977
|
+
}
|
|
978
|
+
const workspaces = await listRemoteWorkspaces(auth.region, auth.regional_token, deps);
|
|
979
|
+
return {
|
|
980
|
+
current: auth.current_workspace?.id || null,
|
|
981
|
+
workspaces: workspaces.map((workspace) => ({
|
|
982
|
+
uid: workspace.uid,
|
|
983
|
+
id: workspace.id,
|
|
984
|
+
teamName: workspace.teamName,
|
|
985
|
+
role: workspace.role,
|
|
986
|
+
nstype: workspace.nstype
|
|
987
|
+
}))
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
__name(listWorkspaces, "listWorkspaces");
|
|
991
|
+
async function switchWorkspace(target, deps = {}) {
|
|
992
|
+
if (!target) {
|
|
993
|
+
throw new Error("Usage: sealos-cli auth switch <namespace-id-or-uid>");
|
|
933
994
|
}
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
995
|
+
const fullDeps = withDeps(deps);
|
|
996
|
+
const auth = loadAuth(fullDeps);
|
|
997
|
+
if (!auth.regional_token) {
|
|
998
|
+
throw new Error("No regional_token found. Please run: sealos-cli login");
|
|
937
999
|
}
|
|
938
|
-
const
|
|
939
|
-
if (
|
|
940
|
-
|
|
941
|
-
string = stringReplaceAll(string, styler.close, styler.open);
|
|
942
|
-
styler = styler.parent;
|
|
943
|
-
}
|
|
1000
|
+
const workspaces = await listRemoteWorkspaces(auth.region, auth.regional_token, fullDeps);
|
|
1001
|
+
if (workspaces.length === 0) {
|
|
1002
|
+
throw new Error("No workspaces found");
|
|
944
1003
|
}
|
|
945
|
-
const
|
|
946
|
-
|
|
947
|
-
|
|
1004
|
+
const targetLower = target.toLowerCase();
|
|
1005
|
+
const match = workspaces.find(
|
|
1006
|
+
(workspace) => workspace.id === target || workspace.uid === target || workspace.id?.toLowerCase().includes(targetLower) || workspace.teamName?.toLowerCase().includes(targetLower)
|
|
1007
|
+
);
|
|
1008
|
+
if (!match?.uid) {
|
|
1009
|
+
const available = workspaces.map((workspace) => ` ${workspace.id || "unknown"} (${workspace.teamName || "unknown"})`).join("\n");
|
|
1010
|
+
throw new Error(`No workspace matching "${target}". Available:
|
|
1011
|
+
${available}`);
|
|
948
1012
|
}
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1013
|
+
fullDeps.stderr.write(`Switching to workspace: ${match.id || match.uid} (${match.teamName || "unknown"})...
|
|
1014
|
+
`);
|
|
1015
|
+
const switchData = await switchRemoteWorkspace(auth.region, auth.regional_token, match.uid, fullDeps);
|
|
1016
|
+
const newToken = switchData.data?.token;
|
|
1017
|
+
if (!newToken) {
|
|
1018
|
+
throw new Error("Switch response missing data.token");
|
|
1019
|
+
}
|
|
1020
|
+
const kubeconfigData = await getKubeconfig(auth.region, newToken, fullDeps);
|
|
1021
|
+
const kubeconfig = kubeconfigData.data?.kubeconfig;
|
|
1022
|
+
if (!kubeconfig) {
|
|
1023
|
+
throw new Error("Kubeconfig response missing data.kubeconfig");
|
|
1024
|
+
}
|
|
1025
|
+
const nextAuth = {
|
|
1026
|
+
...auth,
|
|
1027
|
+
regional_token: newToken,
|
|
1028
|
+
current_workspace: {
|
|
1029
|
+
uid: match.uid,
|
|
1030
|
+
id: match.id,
|
|
1031
|
+
teamName: match.teamName
|
|
1032
|
+
}
|
|
1033
|
+
};
|
|
1034
|
+
saveAuth(nextAuth, fullDeps);
|
|
1035
|
+
saveKubeconfig(kubeconfig, fullDeps);
|
|
1036
|
+
fullDeps.stderr.write(`Switched to workspace: ${match.id || match.uid}
|
|
1037
|
+
`);
|
|
1038
|
+
return {
|
|
1039
|
+
workspace: {
|
|
1040
|
+
uid: match.uid,
|
|
1041
|
+
id: match.id,
|
|
1042
|
+
teamName: match.teamName
|
|
1043
|
+
},
|
|
1044
|
+
kubeconfig_path: fullDeps.paths.kubeconfigPath
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
__name(switchWorkspace, "switchWorkspace");
|
|
955
1048
|
|
|
956
1049
|
// src/lib/output.ts
|
|
957
1050
|
import { table } from "table";
|
|
@@ -3909,92 +4002,9 @@ function spinner(text) {
|
|
|
3909
4002
|
}
|
|
3910
4003
|
__name(spinner, "spinner");
|
|
3911
4004
|
|
|
3912
|
-
// src/lib/errors.ts
|
|
3913
|
-
var CliError = class extends Error {
|
|
3914
|
-
constructor(message, exitCode = 1) {
|
|
3915
|
-
super(message);
|
|
3916
|
-
this.exitCode = exitCode;
|
|
3917
|
-
this.name = "CliError";
|
|
3918
|
-
}
|
|
3919
|
-
exitCode;
|
|
3920
|
-
static {
|
|
3921
|
-
__name(this, "CliError");
|
|
3922
|
-
}
|
|
3923
|
-
};
|
|
3924
|
-
var AuthError = class extends CliError {
|
|
3925
|
-
static {
|
|
3926
|
-
__name(this, "AuthError");
|
|
3927
|
-
}
|
|
3928
|
-
constructor(message = 'Authentication required. Please run "sealos-cli login" first.') {
|
|
3929
|
-
super(message, 1);
|
|
3930
|
-
this.name = "AuthError";
|
|
3931
|
-
}
|
|
3932
|
-
};
|
|
3933
|
-
var ConfigError = class extends CliError {
|
|
3934
|
-
static {
|
|
3935
|
-
__name(this, "ConfigError");
|
|
3936
|
-
}
|
|
3937
|
-
constructor(message) {
|
|
3938
|
-
super(message, 1);
|
|
3939
|
-
this.name = "ConfigError";
|
|
3940
|
-
}
|
|
3941
|
-
};
|
|
3942
|
-
var ApiError = class extends CliError {
|
|
3943
|
-
constructor(message, statusCode, code, details) {
|
|
3944
|
-
super(message, 1);
|
|
3945
|
-
this.statusCode = statusCode;
|
|
3946
|
-
this.code = code;
|
|
3947
|
-
this.details = details;
|
|
3948
|
-
this.name = "ApiError";
|
|
3949
|
-
}
|
|
3950
|
-
statusCode;
|
|
3951
|
-
code;
|
|
3952
|
-
details;
|
|
3953
|
-
static {
|
|
3954
|
-
__name(this, "ApiError");
|
|
3955
|
-
}
|
|
3956
|
-
};
|
|
3957
|
-
function mapApiError(status, body) {
|
|
3958
|
-
const message = body?.error?.message || `API request failed with status ${status}`;
|
|
3959
|
-
if (status === 401) {
|
|
3960
|
-
return new AuthError(message);
|
|
3961
|
-
}
|
|
3962
|
-
return new ApiError(message, status, body?.error?.code, body?.error?.details);
|
|
3963
|
-
}
|
|
3964
|
-
__name(mapApiError, "mapApiError");
|
|
3965
|
-
function handleError(error2) {
|
|
3966
|
-
if (error2 instanceof ApiError) {
|
|
3967
|
-
console.error(source_default.red("Error:"), error2.message);
|
|
3968
|
-
if (error2.details) {
|
|
3969
|
-
if (Array.isArray(error2.details)) {
|
|
3970
|
-
for (const d of error2.details) {
|
|
3971
|
-
console.error(source_default.yellow(` ${d.field}:`), d.message);
|
|
3972
|
-
}
|
|
3973
|
-
} else {
|
|
3974
|
-
console.error(source_default.yellow(" Details:"), error2.details);
|
|
3975
|
-
}
|
|
3976
|
-
}
|
|
3977
|
-
process.exit(error2.exitCode);
|
|
3978
|
-
}
|
|
3979
|
-
if (error2 instanceof CliError) {
|
|
3980
|
-
console.error(source_default.red("Error:"), error2.message);
|
|
3981
|
-
process.exit(error2.exitCode);
|
|
3982
|
-
}
|
|
3983
|
-
if (error2 instanceof Error) {
|
|
3984
|
-
console.error(source_default.red("Error:"), error2.message);
|
|
3985
|
-
if (process.env.DEBUG) {
|
|
3986
|
-
console.error(error2.stack);
|
|
3987
|
-
}
|
|
3988
|
-
process.exit(1);
|
|
3989
|
-
}
|
|
3990
|
-
console.error(source_default.red("Error:"), "An unknown error occurred");
|
|
3991
|
-
process.exit(1);
|
|
3992
|
-
}
|
|
3993
|
-
__name(handleError, "handleError");
|
|
3994
|
-
|
|
3995
4005
|
// src/commands/auth/login.ts
|
|
3996
4006
|
function createLoginCommand() {
|
|
3997
|
-
return new Command("login").description("Login to Sealos Cloud").argument("[region]", "Sealos region URL (e.g., https://usw-1.sealos.io)").option("-t, --token <token>", "Store a regional token without OAuth device login").option("-o, --output <format>", "Output format: json, table", "
|
|
4007
|
+
return new Command("login").description("Login to Sealos Cloud").argument("[region]", "Sealos region URL (e.g., https://usw-1.sealos.io)").option("-t, --token <token>", "Store a regional token without OAuth device login").option("-o, --output <format>", "Output format: json, table", "json").action(async (region, options) => {
|
|
3998
4008
|
try {
|
|
3999
4009
|
const result = options.token ? await loginWithToken(region, options.token) : await loginWithDeviceFlow(region);
|
|
4000
4010
|
if (options.token) {
|
|
@@ -4019,14 +4029,32 @@ __name(createLoginCommand, "createLoginCommand");
|
|
|
4019
4029
|
// src/commands/auth/logout.ts
|
|
4020
4030
|
import { Command as Command2 } from "commander";
|
|
4021
4031
|
function createLogoutCommand() {
|
|
4022
|
-
return new Command2("logout").description("Logout from Sealos Cloud").action(async () => {
|
|
4032
|
+
return new Command2("logout").description("Logout from Sealos Cloud").option("-o, --output <format>", "Output format: json, table", "json").action(async (options) => {
|
|
4023
4033
|
try {
|
|
4024
4034
|
const status = checkAuth();
|
|
4025
4035
|
if (!status.authenticated) {
|
|
4036
|
+
if (options.output === "json") {
|
|
4037
|
+
outputJson({
|
|
4038
|
+
success: true,
|
|
4039
|
+
action: "logout",
|
|
4040
|
+
authenticated: false,
|
|
4041
|
+
changed: false
|
|
4042
|
+
});
|
|
4043
|
+
return;
|
|
4044
|
+
}
|
|
4026
4045
|
warn("You are not logged in");
|
|
4027
4046
|
return;
|
|
4028
4047
|
}
|
|
4029
4048
|
clearAuth();
|
|
4049
|
+
if (options.output === "json") {
|
|
4050
|
+
outputJson({
|
|
4051
|
+
success: true,
|
|
4052
|
+
action: "logout",
|
|
4053
|
+
authenticated: false,
|
|
4054
|
+
changed: true
|
|
4055
|
+
});
|
|
4056
|
+
return;
|
|
4057
|
+
}
|
|
4030
4058
|
success2("Logged out from Sealos Cloud");
|
|
4031
4059
|
} catch (error2) {
|
|
4032
4060
|
handleError(error2);
|
|
@@ -4038,7 +4066,7 @@ __name(createLogoutCommand, "createLogoutCommand");
|
|
|
4038
4066
|
// src/commands/auth/whoami.ts
|
|
4039
4067
|
import { Command as Command3 } from "commander";
|
|
4040
4068
|
function createWhoamiCommand() {
|
|
4041
|
-
return new Command3("whoami").description("Display current user information").option("-o, --output <format>", "Output format: json, table", "
|
|
4069
|
+
return new Command3("whoami").description("Display current user information").option("-o, --output <format>", "Output format: json, table", "json").action(async (options) => {
|
|
4042
4070
|
try {
|
|
4043
4071
|
const authInfo = getAuthInfo();
|
|
4044
4072
|
if (!authInfo.authenticated) {
|
|
@@ -4118,7 +4146,7 @@ function createAuthCommand() {
|
|
|
4118
4146
|
handleError(error2);
|
|
4119
4147
|
}
|
|
4120
4148
|
});
|
|
4121
|
-
authCmd.command("list").description("List all workspaces").option("-o, --output <format>", "Output format: json, table", "
|
|
4149
|
+
authCmd.command("list").description("List all workspaces").option("-o, --output <format>", "Output format: json, table", "json").action(async (options) => {
|
|
4122
4150
|
try {
|
|
4123
4151
|
const result = await listWorkspaces();
|
|
4124
4152
|
if (options.output === "json") {
|
|
@@ -4140,7 +4168,7 @@ function createAuthCommand() {
|
|
|
4140
4168
|
handleError(error2);
|
|
4141
4169
|
}
|
|
4142
4170
|
});
|
|
4143
|
-
authCmd.command("switch").description("Switch workspace").argument("<namespace>", "Workspace id, uid, or team name").option("-o, --output <format>", "Output format: json, table", "
|
|
4171
|
+
authCmd.command("switch").description("Switch workspace").argument("<namespace>", "Workspace id, uid, or team name").option("-o, --output <format>", "Output format: json, table", "json").action(async (namespace, options) => {
|
|
4144
4172
|
try {
|
|
4145
4173
|
const result = await switchWorkspace(namespace);
|
|
4146
4174
|
if (options.output === "json") {
|
|
@@ -4160,7 +4188,7 @@ __name(createAuthCommand, "createAuthCommand");
|
|
|
4160
4188
|
import { Command as Command5 } from "commander";
|
|
4161
4189
|
function createWorkspaceCommand() {
|
|
4162
4190
|
const workspaceCmd = new Command5("workspace").alias("ws").description("Manage workspaces");
|
|
4163
|
-
workspaceCmd.command("switch").description("Switch to another workspace").argument("<namespace>", "Workspace id, uid, or team name").option("-o, --output <format>", "Output format: json, table", "
|
|
4191
|
+
workspaceCmd.command("switch").description("Switch to another workspace").argument("<namespace>", "Workspace id, uid, or team name").option("-o, --output <format>", "Output format: json, table", "json").action(async (namespace, options) => {
|
|
4164
4192
|
try {
|
|
4165
4193
|
const result = await switchWorkspace(namespace);
|
|
4166
4194
|
if (options.output === "json") {
|
|
@@ -4172,7 +4200,7 @@ function createWorkspaceCommand() {
|
|
|
4172
4200
|
handleError(error2);
|
|
4173
4201
|
}
|
|
4174
4202
|
});
|
|
4175
|
-
workspaceCmd.command("list").description("List all workspaces").option("-o, --output <format>", "Output format: json, table", "
|
|
4203
|
+
workspaceCmd.command("list").description("List all workspaces").option("-o, --output <format>", "Output format: json, table", "json").action(async (options) => {
|
|
4176
4204
|
try {
|
|
4177
4205
|
const result = await listWorkspaces();
|
|
4178
4206
|
if (options.output === "json") {
|
|
@@ -4194,7 +4222,7 @@ function createWorkspaceCommand() {
|
|
|
4194
4222
|
handleError(error2);
|
|
4195
4223
|
}
|
|
4196
4224
|
});
|
|
4197
|
-
workspaceCmd.command("current").description("Show current workspace").option("-o, --output <format>", "Output format: json, table", "
|
|
4225
|
+
workspaceCmd.command("current").description("Show current workspace").option("-o, --output <format>", "Output format: json, table", "json").action(async (options) => {
|
|
4198
4226
|
try {
|
|
4199
4227
|
const authInfo = getAuthInfo();
|
|
4200
4228
|
if (!authInfo.authenticated) {
|
|
@@ -5146,7 +5174,7 @@ function printTemplates(templates) {
|
|
|
5146
5174
|
__name(printTemplates, "printTemplates");
|
|
5147
5175
|
function createDevboxCommand() {
|
|
5148
5176
|
const devboxCmd = new Command6("devbox").alias("dev").description("Manage devbox instances");
|
|
5149
|
-
devboxCmd.command("list").description("List all devboxes").option("-o, --output <format>", "Output format (json|table)", "
|
|
5177
|
+
devboxCmd.command("list").description("List all devboxes").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading devboxes..." }, async (ctx, options) => {
|
|
5150
5178
|
const client = createDevboxClient();
|
|
5151
5179
|
const { data, error: error2, response } = await client.GET("/devbox", {
|
|
5152
5180
|
headers: ctx.auth
|
|
@@ -5159,7 +5187,7 @@ function createDevboxCommand() {
|
|
|
5159
5187
|
}
|
|
5160
5188
|
printDevboxList(data);
|
|
5161
5189
|
}));
|
|
5162
|
-
devboxCmd.command("create").description("Create a new devbox").requiredOption("--name <name>", "Devbox name").option("--runtime <runtime>", "Runtime environment name").option("--template <runtime>", "Alias for --runtime").option("--cpu <cpu>", "CPU cores", "1").option("--memory <memory>", "Memory in GB", "2").option("--port <spec>", "Port spec, e.g. 8080:http:public or number=8080,protocol=http", collectOption, []).option("--env <NAME=VALUE>", "Environment variable", collectOption, []).option("--secret-env <NAME=SECRET:KEY>", "Environment variable from secret", collectOption, []).option("--autostart", "Auto start devbox after creation").option("-o, --output <format>", "Output format (json|table)", "
|
|
5190
|
+
devboxCmd.command("create").description("Create a new devbox").requiredOption("--name <name>", "Devbox name").option("--runtime <runtime>", "Runtime environment name").option("--template <runtime>", "Alias for --runtime").option("--cpu <cpu>", "CPU cores", "1").option("--memory <memory>", "Memory in GB", "2").option("--port <spec>", "Port spec, e.g. 8080:http:public or number=8080,protocol=http", collectOption, []).option("--env <NAME=VALUE>", "Environment variable", collectOption, []).option("--secret-env <NAME=SECRET:KEY>", "Environment variable from secret", collectOption, []).option("--autostart", "Auto start devbox after creation").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Creating devbox..." }, async (ctx, options) => {
|
|
5163
5191
|
const client = createDevboxClient();
|
|
5164
5192
|
const { data, error: error2, response } = await client.POST("/devbox", {
|
|
5165
5193
|
headers: ctx.auth,
|
|
@@ -5174,7 +5202,7 @@ function createDevboxCommand() {
|
|
|
5174
5202
|
ctx.spinner.succeed(`Devbox "${data.name}" created`);
|
|
5175
5203
|
printCreateResult(data);
|
|
5176
5204
|
}));
|
|
5177
|
-
devboxCmd.command("get <name>").description("Get devbox details").option("-o, --output <format>", "Output format (json|table)", "
|
|
5205
|
+
devboxCmd.command("get <name>").description("Get devbox details").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading devbox..." }, async (ctx, name, options) => {
|
|
5178
5206
|
const client = createDevboxClient();
|
|
5179
5207
|
const { data, error: error2, response } = await client.GET("/devbox/{name}", {
|
|
5180
5208
|
headers: ctx.auth,
|
|
@@ -5190,7 +5218,7 @@ function createDevboxCommand() {
|
|
|
5190
5218
|
}
|
|
5191
5219
|
printDevboxDetail(data);
|
|
5192
5220
|
}));
|
|
5193
|
-
devboxCmd.command("update <name>").description("Update devbox resources or ports").option("--cpu <cpu>", "CPU cores").option("--memory <memory>", "Memory in GB").option("--port <spec>", "Port spec. Existing ports can include portName=...", collectOption, []).action(withAuth({ spinnerText: "Updating devbox..." }, async (ctx, name, options) => {
|
|
5221
|
+
devboxCmd.command("update <name>").description("Update devbox resources or ports").option("--cpu <cpu>", "CPU cores").option("--memory <memory>", "Memory in GB").option("--port <spec>", "Port spec. Existing ports can include portName=...", collectOption, []).option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Updating devbox..." }, async (ctx, name, options) => {
|
|
5194
5222
|
const client = createDevboxClient();
|
|
5195
5223
|
const { error: error2, response } = await client.PATCH("/devbox/{name}", {
|
|
5196
5224
|
headers: ctx.auth,
|
|
@@ -5200,9 +5228,20 @@ function createDevboxCommand() {
|
|
|
5200
5228
|
body: buildUpdateDevboxBody(options)
|
|
5201
5229
|
});
|
|
5202
5230
|
if (error2) throw mapApiError(response.status, error2);
|
|
5231
|
+
if (options.output === "json") {
|
|
5232
|
+
ctx.spinner.stop();
|
|
5233
|
+
outputJson({
|
|
5234
|
+
success: true,
|
|
5235
|
+
action: "update",
|
|
5236
|
+
resource: "devbox",
|
|
5237
|
+
name,
|
|
5238
|
+
status: "requested"
|
|
5239
|
+
});
|
|
5240
|
+
return;
|
|
5241
|
+
}
|
|
5203
5242
|
ctx.spinner.succeed(`Devbox "${name}" update requested`);
|
|
5204
5243
|
}));
|
|
5205
|
-
devboxCmd.command("delete <name>").description("Delete a devbox").alias("rm").action(withAuth({ spinnerText: "Deleting devbox..." }, async (ctx, name) => {
|
|
5244
|
+
devboxCmd.command("delete <name>").description("Delete a devbox").alias("rm").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Deleting devbox..." }, async (ctx, name, options) => {
|
|
5206
5245
|
const client = createDevboxClient();
|
|
5207
5246
|
const { error: error2, response } = await client.DELETE("/devbox/{name}", {
|
|
5208
5247
|
headers: ctx.auth,
|
|
@@ -5211,6 +5250,17 @@ function createDevboxCommand() {
|
|
|
5211
5250
|
}
|
|
5212
5251
|
});
|
|
5213
5252
|
if (error2) throw mapApiError(response.status, error2);
|
|
5253
|
+
if (options.output === "json") {
|
|
5254
|
+
ctx.spinner.stop();
|
|
5255
|
+
outputJson({
|
|
5256
|
+
success: true,
|
|
5257
|
+
action: "delete",
|
|
5258
|
+
resource: "devbox",
|
|
5259
|
+
name,
|
|
5260
|
+
status: "deleted"
|
|
5261
|
+
});
|
|
5262
|
+
return;
|
|
5263
|
+
}
|
|
5214
5264
|
ctx.spinner.succeed(`Devbox "${name}" deleted`);
|
|
5215
5265
|
}));
|
|
5216
5266
|
const lifecycleActions = [
|
|
@@ -5222,7 +5272,7 @@ function createDevboxCommand() {
|
|
|
5222
5272
|
for (const action of lifecycleActions) {
|
|
5223
5273
|
const command = devboxCmd.command(`${action.name} <name>`).description(`${action.name.charAt(0).toUpperCase()}${action.name.slice(1)} a devbox`);
|
|
5224
5274
|
if (action.alias) command.alias(action.alias);
|
|
5225
|
-
command.action(withAuth({ spinnerText: action.spinnerText }, async (ctx, name) => {
|
|
5275
|
+
command.option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: action.spinnerText }, async (ctx, name, options) => {
|
|
5226
5276
|
const client = createDevboxClient();
|
|
5227
5277
|
const { error: error2, response } = await client.POST(action.endpoint, {
|
|
5228
5278
|
headers: ctx.auth,
|
|
@@ -5232,10 +5282,21 @@ function createDevboxCommand() {
|
|
|
5232
5282
|
body: {}
|
|
5233
5283
|
});
|
|
5234
5284
|
if (error2) throw mapApiError(response.status, error2);
|
|
5285
|
+
if (options.output === "json") {
|
|
5286
|
+
ctx.spinner.stop();
|
|
5287
|
+
outputJson({
|
|
5288
|
+
success: true,
|
|
5289
|
+
action: action.name,
|
|
5290
|
+
resource: "devbox",
|
|
5291
|
+
name,
|
|
5292
|
+
status: "requested"
|
|
5293
|
+
});
|
|
5294
|
+
return;
|
|
5295
|
+
}
|
|
5235
5296
|
ctx.spinner.succeed(`Devbox "${name}" ${action.done}`);
|
|
5236
5297
|
}));
|
|
5237
5298
|
}
|
|
5238
|
-
devboxCmd.command("autostart <name>").description("Configure devbox autostart").option("--exec-command <command>", "Command to execute when the devbox starts").action(withAuth({ spinnerText: "Configuring autostart..." }, async (ctx, name, options) => {
|
|
5299
|
+
devboxCmd.command("autostart <name>").description("Configure devbox autostart").option("--exec-command <command>", "Command to execute when the devbox starts").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Configuring autostart..." }, async (ctx, name, options) => {
|
|
5239
5300
|
const client = createDevboxClient();
|
|
5240
5301
|
const body = options.execCommand ? { execCommand: options.execCommand } : {};
|
|
5241
5302
|
const { error: error2, response } = await client.POST("/devbox/{name}/autostart", {
|
|
@@ -5246,9 +5307,21 @@ function createDevboxCommand() {
|
|
|
5246
5307
|
body
|
|
5247
5308
|
});
|
|
5248
5309
|
if (error2) throw mapApiError(response.status, error2);
|
|
5310
|
+
if (options.output === "json") {
|
|
5311
|
+
ctx.spinner.stop();
|
|
5312
|
+
outputJson({
|
|
5313
|
+
success: true,
|
|
5314
|
+
action: "autostart",
|
|
5315
|
+
resource: "devbox",
|
|
5316
|
+
name,
|
|
5317
|
+
execCommand: options.execCommand ?? null,
|
|
5318
|
+
status: "configured"
|
|
5319
|
+
});
|
|
5320
|
+
return;
|
|
5321
|
+
}
|
|
5249
5322
|
ctx.spinner.succeed(`Autostart configured for "${name}"`);
|
|
5250
5323
|
}));
|
|
5251
|
-
devboxCmd.command("monitor <name>").description("Get devbox monitoring data").option("--start <timestamp>", "Start timestamp in seconds or milliseconds").option("--end <timestamp>", "End timestamp in seconds or milliseconds").option("--step <step>", "Sampling interval, e.g. 2m").option("-o, --output <format>", "Output format (json|table)", "
|
|
5324
|
+
devboxCmd.command("monitor <name>").description("Get devbox monitoring data").option("--start <timestamp>", "Start timestamp in seconds or milliseconds").option("--end <timestamp>", "End timestamp in seconds or milliseconds").option("--step <step>", "Sampling interval, e.g. 2m").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading monitor data..." }, async (ctx, name, options) => {
|
|
5252
5325
|
const client = createDevboxClient();
|
|
5253
5326
|
const { data, error: error2, response } = await client.GET("/devbox/{name}/monitor", {
|
|
5254
5327
|
headers: ctx.auth,
|
|
@@ -5269,7 +5342,7 @@ function createDevboxCommand() {
|
|
|
5269
5342
|
}
|
|
5270
5343
|
printMonitor(data);
|
|
5271
5344
|
}));
|
|
5272
|
-
devboxCmd.command("templates").description("List available devbox templates").option("-o, --output <format>", "Output format (json|table)", "
|
|
5345
|
+
devboxCmd.command("templates").description("List available devbox templates").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading devbox templates..." }, async (ctx, options) => {
|
|
5273
5346
|
const client = createDevboxClient();
|
|
5274
5347
|
const { data, error: error2, response } = await client.GET("/devbox/templates", {
|
|
5275
5348
|
headers: ctx.auth
|
|
@@ -5283,7 +5356,7 @@ function createDevboxCommand() {
|
|
|
5283
5356
|
printTemplates(data);
|
|
5284
5357
|
}));
|
|
5285
5358
|
const releasesCommand = devboxCmd.command("releases").description("Manage devbox releases");
|
|
5286
|
-
releasesCommand.command("list <name>").description("List devbox releases").option("-o, --output <format>", "Output format (json|table)", "
|
|
5359
|
+
releasesCommand.command("list <name>").description("List devbox releases").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading releases..." }, async (ctx, name, options) => {
|
|
5287
5360
|
const client = createDevboxClient();
|
|
5288
5361
|
const { data, error: error2, response } = await client.GET("/devbox/{name}/releases", {
|
|
5289
5362
|
headers: ctx.auth,
|
|
@@ -5299,7 +5372,7 @@ function createDevboxCommand() {
|
|
|
5299
5372
|
}
|
|
5300
5373
|
printReleases(data);
|
|
5301
5374
|
}));
|
|
5302
|
-
releasesCommand.command("create <name>").description("Create a devbox release").requiredOption("--tag <tag>", "Release tag").option("--description <description>", "Release description").option("--exec-command <command>", "Autostart command after release restart").option("--no-start", "Keep devbox stopped after the release build completes").action(withAuth({ spinnerText: "Creating release..." }, async (ctx, name, options) => {
|
|
5375
|
+
releasesCommand.command("create <name>").description("Create a devbox release").requiredOption("--tag <tag>", "Release tag").option("--description <description>", "Release description").option("--exec-command <command>", "Autostart command after release restart").option("--no-start", "Keep devbox stopped after the release build completes").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Creating release..." }, async (ctx, name, options) => {
|
|
5303
5376
|
const client = createDevboxClient();
|
|
5304
5377
|
const { data, error: error2, response } = await client.POST("/devbox/{name}/releases", {
|
|
5305
5378
|
headers: ctx.auth,
|
|
@@ -5309,9 +5382,14 @@ function createDevboxCommand() {
|
|
|
5309
5382
|
body: buildReleaseBody(options)
|
|
5310
5383
|
});
|
|
5311
5384
|
if (error2) throw mapApiError(response.status, error2);
|
|
5385
|
+
if (options.output === "json") {
|
|
5386
|
+
ctx.spinner.stop();
|
|
5387
|
+
outputJson(data);
|
|
5388
|
+
return;
|
|
5389
|
+
}
|
|
5312
5390
|
ctx.spinner.succeed(`Release "${options.tag}" accepted for "${data.name}" (${data.status})`);
|
|
5313
5391
|
}));
|
|
5314
|
-
releasesCommand.command("delete <name> <tag>").alias("rm").description("Delete a devbox release").action(withAuth({ spinnerText: "Deleting release..." }, async (ctx, name, tag) => {
|
|
5392
|
+
releasesCommand.command("delete <name> <tag>").alias("rm").description("Delete a devbox release").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Deleting release..." }, async (ctx, name, tag, options) => {
|
|
5315
5393
|
const client = createDevboxClient();
|
|
5316
5394
|
const { error: error2, response } = await client.DELETE("/devbox/{name}/releases/{tag}", {
|
|
5317
5395
|
headers: ctx.auth,
|
|
@@ -5320,9 +5398,21 @@ function createDevboxCommand() {
|
|
|
5320
5398
|
}
|
|
5321
5399
|
});
|
|
5322
5400
|
if (error2) throw mapApiError(response.status, error2);
|
|
5401
|
+
if (options.output === "json") {
|
|
5402
|
+
ctx.spinner.stop();
|
|
5403
|
+
outputJson({
|
|
5404
|
+
success: true,
|
|
5405
|
+
action: "delete",
|
|
5406
|
+
resource: "devbox-release",
|
|
5407
|
+
name,
|
|
5408
|
+
tag,
|
|
5409
|
+
status: "deleted"
|
|
5410
|
+
});
|
|
5411
|
+
return;
|
|
5412
|
+
}
|
|
5323
5413
|
ctx.spinner.succeed(`Release "${tag}" deleted for "${name}"`);
|
|
5324
5414
|
}));
|
|
5325
|
-
releasesCommand.command("deploy <name> <tag>").description("Deploy a release to AppLaunchpad").action(withAuth({ spinnerText: "Deploying release..." }, async (ctx, name, tag) => {
|
|
5415
|
+
releasesCommand.command("deploy <name> <tag>").description("Deploy a release to AppLaunchpad").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Deploying release..." }, async (ctx, name, tag, options) => {
|
|
5326
5416
|
const client = createDevboxClient();
|
|
5327
5417
|
const { error: error2, response } = await client.POST("/devbox/{name}/releases/{tag}/deploy", {
|
|
5328
5418
|
headers: ctx.auth,
|
|
@@ -5331,9 +5421,21 @@ function createDevboxCommand() {
|
|
|
5331
5421
|
}
|
|
5332
5422
|
});
|
|
5333
5423
|
if (error2) throw mapApiError(response.status, error2);
|
|
5424
|
+
if (options.output === "json") {
|
|
5425
|
+
ctx.spinner.stop();
|
|
5426
|
+
outputJson({
|
|
5427
|
+
success: true,
|
|
5428
|
+
action: "deploy",
|
|
5429
|
+
resource: "devbox-release",
|
|
5430
|
+
name,
|
|
5431
|
+
tag,
|
|
5432
|
+
status: "deployed"
|
|
5433
|
+
});
|
|
5434
|
+
return;
|
|
5435
|
+
}
|
|
5334
5436
|
ctx.spinner.succeed(`Release "${tag}" deployed for "${name}"`);
|
|
5335
5437
|
}));
|
|
5336
|
-
devboxCmd.command("deployments <name>").description("List deployed applications from a devbox").option("-o, --output <format>", "Output format (json|table)", "
|
|
5438
|
+
devboxCmd.command("deployments <name>").description("List deployed applications from a devbox").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading deployments..." }, async (ctx, name, options) => {
|
|
5337
5439
|
const client = createDevboxClient();
|
|
5338
5440
|
const { data, error: error2, response } = await client.GET("/devbox/{name}/deployments", {
|
|
5339
5441
|
headers: ctx.auth,
|
|
@@ -5581,7 +5683,7 @@ function printConnectionDetail(connection) {
|
|
|
5581
5683
|
__name(printConnectionDetail, "printConnectionDetail");
|
|
5582
5684
|
function createDatabaseCommand() {
|
|
5583
5685
|
const dbCmd = new Command7("database").alias("db").description("Manage databases");
|
|
5584
|
-
dbCmd.command("list").description("List databases").option("-o, --output <format>", "Output format (json|table)", "
|
|
5686
|
+
dbCmd.command("list").description("List databases").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading databases..." }, async (ctx, options) => {
|
|
5585
5687
|
const client = createDatabaseClient();
|
|
5586
5688
|
const { data, error: error2, response } = await client.GET("/databases", {
|
|
5587
5689
|
headers: ctx.auth
|
|
@@ -5620,7 +5722,7 @@ function createDatabaseCommand() {
|
|
|
5620
5722
|
}
|
|
5621
5723
|
outputTable(rows);
|
|
5622
5724
|
}));
|
|
5623
|
-
dbCmd.command("versions").description("List supported database versions (public endpoint)").option("-o, --output <format>", "Output format (json|table)", "
|
|
5725
|
+
dbCmd.command("versions").description("List supported database versions (public endpoint)").option("-o, --output <format>", "Output format (json|table)", "json").option("--host <host>", "Sealos region host for public version lookup, e.g. https://gzg.sealos.run").option("--type <type>", "Filter versions by database type").action(withErrorHandling({ spinnerText: "Loading versions..." }, async (ctx, options) => {
|
|
5624
5726
|
const client = createDatabaseClient({ baseUrl: options.host });
|
|
5625
5727
|
const { data, error: error2, response } = await client.GET("/databases/versions");
|
|
5626
5728
|
if (error2) throw mapApiError(response.status, error2);
|
|
@@ -5656,7 +5758,7 @@ function createDatabaseCommand() {
|
|
|
5656
5758
|
}
|
|
5657
5759
|
outputTable(rows);
|
|
5658
5760
|
}));
|
|
5659
|
-
dbCmd.command("create <type>").description("Create a database").requiredOption("--name <name>", "Database name").option("--version <version>", "Database version").option("--cpu <cpu>", "CPU cores per replica", "1").option("--memory <memory>", "Memory in GB per replica", "1").option("--storage <storage>", "Storage in GB per replica", "3").option("--replicas <replicas>", "Replica count", "1").option("--termination-policy <policy>", "Termination policy (delete|wipeout)").option("--backup-start", "Enable automatic backups").option("--backup-type <type>", "Automatic backup frequency (day|hour|week)").option("--backup-week <day>", "Weekday for weekly backups", collectOption2, []).option("--backup-hour <hour>", "Backup hour (00-23)").option("--backup-minute <minute>", "Backup minute (00-59)").option("--backup-save-time <count>", "Retention count").option("--backup-save-type <type>", "Retention unit (days|hours|weeks|months)").option("--param <KEY=VALUE>", "Database parameter override", collectOption2, []).option("-o, --output <format>", "Output format (json|table)", "
|
|
5761
|
+
dbCmd.command("create <type>").description("Create a database").requiredOption("--name <name>", "Database name").option("--version <version>", "Database version").option("--cpu <cpu>", "CPU cores per replica", "1").option("--memory <memory>", "Memory in GB per replica", "1").option("--storage <storage>", "Storage in GB per replica", "3").option("--replicas <replicas>", "Replica count", "1").option("--termination-policy <policy>", "Termination policy (delete|wipeout)").option("--backup-start", "Enable automatic backups").option("--backup-type <type>", "Automatic backup frequency (day|hour|week)").option("--backup-week <day>", "Weekday for weekly backups", collectOption2, []).option("--backup-hour <hour>", "Backup hour (00-23)").option("--backup-minute <minute>", "Backup minute (00-59)").option("--backup-save-time <count>", "Retention count").option("--backup-save-type <type>", "Retention unit (days|hours|weeks|months)").option("--param <KEY=VALUE>", "Database parameter override", collectOption2, []).option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({
|
|
5660
5762
|
spinnerText: "Creating database..."
|
|
5661
5763
|
}, async (ctx, type, options) => {
|
|
5662
5764
|
const client = createDatabaseClient();
|
|
@@ -5691,7 +5793,7 @@ function createDatabaseCommand() {
|
|
|
5691
5793
|
console.log(source_default.dim(` Provisioning status: ${data.status}`));
|
|
5692
5794
|
console.log(source_default.dim(` Next: sealos-cli database get ${data.name}`));
|
|
5693
5795
|
}));
|
|
5694
|
-
dbCmd.command("get <name>").alias("describe").description("Get database details").option("-o, --output <format>", "Output format (json|table)", "
|
|
5796
|
+
dbCmd.command("get <name>").alias("describe").description("Get database details").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading database..." }, async (ctx, name, options) => {
|
|
5695
5797
|
const client = createDatabaseClient();
|
|
5696
5798
|
const { data, error: error2, response } = await client.GET("/databases/{databaseName}", {
|
|
5697
5799
|
headers: ctx.auth,
|
|
@@ -5707,7 +5809,7 @@ function createDatabaseCommand() {
|
|
|
5707
5809
|
}
|
|
5708
5810
|
printDatabaseDetail(data);
|
|
5709
5811
|
}));
|
|
5710
|
-
dbCmd.command("connection <name>").description("Show database connection details").option("-o, --output <format>", "Output format (json|table)", "
|
|
5812
|
+
dbCmd.command("connection <name>").description("Show database connection details").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading connection details..." }, async (ctx, name, options) => {
|
|
5711
5813
|
const client = createDatabaseClient();
|
|
5712
5814
|
const { data, error: error2, response } = await client.GET("/databases/{databaseName}", {
|
|
5713
5815
|
headers: ctx.auth,
|
|
@@ -5723,7 +5825,7 @@ function createDatabaseCommand() {
|
|
|
5723
5825
|
}
|
|
5724
5826
|
printConnectionDetail(data.connection);
|
|
5725
5827
|
}));
|
|
5726
|
-
dbCmd.command("update <name>").description("Update database resources").option("--cpu <cpu>", "CPU cores per replica").option("--memory <memory>", "Memory in GB per replica").option("--storage <storage>", "Storage in GB per replica").option("--replicas <replicas>", "Replica count").action(withAuth({
|
|
5828
|
+
dbCmd.command("update <name>").description("Update database resources").option("--cpu <cpu>", "CPU cores per replica").option("--memory <memory>", "Memory in GB per replica").option("--storage <storage>", "Storage in GB per replica").option("--replicas <replicas>", "Replica count").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({
|
|
5727
5829
|
spinnerText: "Updating database..."
|
|
5728
5830
|
}, async (ctx, name, options) => {
|
|
5729
5831
|
const quota = buildQuota(options);
|
|
@@ -5739,9 +5841,20 @@ function createDatabaseCommand() {
|
|
|
5739
5841
|
body: { quota }
|
|
5740
5842
|
});
|
|
5741
5843
|
if (error2) throw mapApiError(response.status, error2);
|
|
5844
|
+
if (options.output === "json") {
|
|
5845
|
+
ctx.spinner.stop();
|
|
5846
|
+
outputJson({
|
|
5847
|
+
success: true,
|
|
5848
|
+
action: "update",
|
|
5849
|
+
resource: "database",
|
|
5850
|
+
name,
|
|
5851
|
+
status: "requested"
|
|
5852
|
+
});
|
|
5853
|
+
return;
|
|
5854
|
+
}
|
|
5742
5855
|
ctx.spinner.succeed(`Database "${name}" update requested`);
|
|
5743
5856
|
}));
|
|
5744
|
-
dbCmd.command("start <name>").description("Start a database").action(withAuth({ spinnerText: "Starting database..." }, async (ctx, name) => {
|
|
5857
|
+
dbCmd.command("start <name>").description("Start a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Starting database..." }, async (ctx, name, options) => {
|
|
5745
5858
|
const client = createDatabaseClient();
|
|
5746
5859
|
const { error: error2, response } = await client.POST("/databases/{databaseName}/start", {
|
|
5747
5860
|
headers: ctx.auth,
|
|
@@ -5750,9 +5863,20 @@ function createDatabaseCommand() {
|
|
|
5750
5863
|
}
|
|
5751
5864
|
});
|
|
5752
5865
|
if (error2) throw mapApiError(response.status, error2);
|
|
5866
|
+
if (options.output === "json") {
|
|
5867
|
+
ctx.spinner.stop();
|
|
5868
|
+
outputJson({
|
|
5869
|
+
success: true,
|
|
5870
|
+
action: "start",
|
|
5871
|
+
resource: "database",
|
|
5872
|
+
name,
|
|
5873
|
+
status: "requested"
|
|
5874
|
+
});
|
|
5875
|
+
return;
|
|
5876
|
+
}
|
|
5753
5877
|
ctx.spinner.succeed(`Database "${name}" start requested`);
|
|
5754
5878
|
}));
|
|
5755
|
-
dbCmd.command("pause <name>").alias("stop").description("Pause a database").action(withAuth({ spinnerText: "Pausing database..." }, async (ctx, name) => {
|
|
5879
|
+
dbCmd.command("pause <name>").alias("stop").description("Pause a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Pausing database..." }, async (ctx, name, options) => {
|
|
5756
5880
|
const client = createDatabaseClient();
|
|
5757
5881
|
const { error: error2, response } = await client.POST("/databases/{databaseName}/pause", {
|
|
5758
5882
|
headers: ctx.auth,
|
|
@@ -5761,9 +5885,20 @@ function createDatabaseCommand() {
|
|
|
5761
5885
|
}
|
|
5762
5886
|
});
|
|
5763
5887
|
if (error2) throw mapApiError(response.status, error2);
|
|
5888
|
+
if (options.output === "json") {
|
|
5889
|
+
ctx.spinner.stop();
|
|
5890
|
+
outputJson({
|
|
5891
|
+
success: true,
|
|
5892
|
+
action: "pause",
|
|
5893
|
+
resource: "database",
|
|
5894
|
+
name,
|
|
5895
|
+
status: "requested"
|
|
5896
|
+
});
|
|
5897
|
+
return;
|
|
5898
|
+
}
|
|
5764
5899
|
ctx.spinner.succeed(`Database "${name}" pause requested`);
|
|
5765
5900
|
}));
|
|
5766
|
-
dbCmd.command("restart <name>").description("Restart a database").action(withAuth({ spinnerText: "Restarting database..." }, async (ctx, name) => {
|
|
5901
|
+
dbCmd.command("restart <name>").description("Restart a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Restarting database..." }, async (ctx, name, options) => {
|
|
5767
5902
|
const client = createDatabaseClient();
|
|
5768
5903
|
const { error: error2, response } = await client.POST("/databases/{databaseName}/restart", {
|
|
5769
5904
|
headers: ctx.auth,
|
|
@@ -5772,9 +5907,20 @@ function createDatabaseCommand() {
|
|
|
5772
5907
|
}
|
|
5773
5908
|
});
|
|
5774
5909
|
if (error2) throw mapApiError(response.status, error2);
|
|
5910
|
+
if (options.output === "json") {
|
|
5911
|
+
ctx.spinner.stop();
|
|
5912
|
+
outputJson({
|
|
5913
|
+
success: true,
|
|
5914
|
+
action: "restart",
|
|
5915
|
+
resource: "database",
|
|
5916
|
+
name,
|
|
5917
|
+
status: "requested"
|
|
5918
|
+
});
|
|
5919
|
+
return;
|
|
5920
|
+
}
|
|
5775
5921
|
ctx.spinner.succeed(`Database "${name}" restart requested`);
|
|
5776
5922
|
}));
|
|
5777
|
-
dbCmd.command("delete <name>").description("Delete a database").option("-f, --force", "Delete without confirmation").action(withAuth({ spinnerText: "Deleting database..." }, async (ctx, name) => {
|
|
5923
|
+
dbCmd.command("delete <name>").description("Delete a database").option("-f, --force", "Delete without confirmation").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Deleting database..." }, async (ctx, name, options) => {
|
|
5778
5924
|
const client = createDatabaseClient();
|
|
5779
5925
|
const { error: error2, response } = await client.DELETE("/databases/{databaseName}", {
|
|
5780
5926
|
headers: ctx.auth,
|
|
@@ -5783,9 +5929,20 @@ function createDatabaseCommand() {
|
|
|
5783
5929
|
}
|
|
5784
5930
|
});
|
|
5785
5931
|
if (error2) throw mapApiError(response.status, error2);
|
|
5932
|
+
if (options.output === "json") {
|
|
5933
|
+
ctx.spinner.stop();
|
|
5934
|
+
outputJson({
|
|
5935
|
+
success: true,
|
|
5936
|
+
action: "delete",
|
|
5937
|
+
resource: "database",
|
|
5938
|
+
name,
|
|
5939
|
+
status: "requested"
|
|
5940
|
+
});
|
|
5941
|
+
return;
|
|
5942
|
+
}
|
|
5786
5943
|
ctx.spinner.succeed(`Database "${name}" delete requested`);
|
|
5787
5944
|
}));
|
|
5788
|
-
dbCmd.command("backups <name>").description("List backups for a database").option("-o, --output <format>", "Output format (json|table)", "
|
|
5945
|
+
dbCmd.command("backups <name>").description("List backups for a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Loading backups..." }, async (ctx, name, options) => {
|
|
5789
5946
|
const client = createDatabaseClient();
|
|
5790
5947
|
const { data, error: error2, response } = await client.GET("/databases/{databaseName}/backups", {
|
|
5791
5948
|
headers: ctx.auth,
|
|
@@ -5819,7 +5976,7 @@ function createDatabaseCommand() {
|
|
|
5819
5976
|
}
|
|
5820
5977
|
outputTable(rows);
|
|
5821
5978
|
}));
|
|
5822
|
-
dbCmd.command("backup <name>").description("Create a database backup").option("--name <backupName>", "Backup name").option("--description <description>", "Backup description").action(withAuth({
|
|
5979
|
+
dbCmd.command("backup <name>").description("Create a database backup").option("--name <backupName>", "Backup name").option("--description <description>", "Backup description").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({
|
|
5823
5980
|
spinnerText: "Creating backup..."
|
|
5824
5981
|
}, async (ctx, name, options) => {
|
|
5825
5982
|
const client = createDatabaseClient();
|
|
@@ -5834,11 +5991,23 @@ function createDatabaseCommand() {
|
|
|
5834
5991
|
body
|
|
5835
5992
|
});
|
|
5836
5993
|
if (error2) throw mapApiError(response.status, error2);
|
|
5994
|
+
if (options.output === "json") {
|
|
5995
|
+
ctx.spinner.stop();
|
|
5996
|
+
outputJson({
|
|
5997
|
+
success: true,
|
|
5998
|
+
action: "backup",
|
|
5999
|
+
resource: "database",
|
|
6000
|
+
name,
|
|
6001
|
+
backupName: options.name ?? null,
|
|
6002
|
+
status: "requested"
|
|
6003
|
+
});
|
|
6004
|
+
return;
|
|
6005
|
+
}
|
|
5837
6006
|
ctx.spinner.succeed(`Backup requested for database "${name}"`);
|
|
5838
6007
|
}));
|
|
5839
|
-
dbCmd.command("backup-delete <databaseName> <backupName>").description("Delete a database backup").action(withAuth({
|
|
6008
|
+
dbCmd.command("backup-delete <databaseName> <backupName>").description("Delete a database backup").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({
|
|
5840
6009
|
spinnerText: "Deleting backup..."
|
|
5841
|
-
}, async (ctx, databaseName, backupName) => {
|
|
6010
|
+
}, async (ctx, databaseName, backupName, options) => {
|
|
5842
6011
|
const client = createDatabaseClient();
|
|
5843
6012
|
const { error: error2, response } = await client.DELETE("/databases/{databaseName}/backups/{backupName}", {
|
|
5844
6013
|
headers: ctx.auth,
|
|
@@ -5847,9 +6016,21 @@ function createDatabaseCommand() {
|
|
|
5847
6016
|
}
|
|
5848
6017
|
});
|
|
5849
6018
|
if (error2) throw mapApiError(response.status, error2);
|
|
6019
|
+
if (options.output === "json") {
|
|
6020
|
+
ctx.spinner.stop();
|
|
6021
|
+
outputJson({
|
|
6022
|
+
success: true,
|
|
6023
|
+
action: "backup-delete",
|
|
6024
|
+
resource: "database-backup",
|
|
6025
|
+
databaseName,
|
|
6026
|
+
backupName,
|
|
6027
|
+
status: "deleted"
|
|
6028
|
+
});
|
|
6029
|
+
return;
|
|
6030
|
+
}
|
|
5850
6031
|
ctx.spinner.succeed(`Backup "${backupName}" deleted`);
|
|
5851
6032
|
}));
|
|
5852
|
-
dbCmd.command("restore <databaseName>").description("Restore a database from a backup").requiredOption("--from <backupName>", "Backup name to restore from").option("--name <name>", "Name for the restored database").option("--replicas <replicas>", "Replica count for the restored database").action(withAuth({
|
|
6033
|
+
dbCmd.command("restore <databaseName>").description("Restore a database from a backup").requiredOption("--from <backupName>", "Backup name to restore from").option("--name <name>", "Name for the restored database").option("--replicas <replicas>", "Replica count for the restored database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({
|
|
5853
6034
|
spinnerText: "Restoring database..."
|
|
5854
6035
|
}, async (ctx, databaseName, options) => {
|
|
5855
6036
|
const client = createDatabaseClient();
|
|
@@ -5864,9 +6045,22 @@ function createDatabaseCommand() {
|
|
|
5864
6045
|
body
|
|
5865
6046
|
});
|
|
5866
6047
|
if (error2) throw mapApiError(response.status, error2);
|
|
6048
|
+
if (options.output === "json") {
|
|
6049
|
+
ctx.spinner.stop();
|
|
6050
|
+
outputJson({
|
|
6051
|
+
success: true,
|
|
6052
|
+
action: "restore",
|
|
6053
|
+
resource: "database",
|
|
6054
|
+
databaseName,
|
|
6055
|
+
backupName: options.from,
|
|
6056
|
+
restoredName: options.name ?? null,
|
|
6057
|
+
status: "requested"
|
|
6058
|
+
});
|
|
6059
|
+
return;
|
|
6060
|
+
}
|
|
5867
6061
|
ctx.spinner.succeed(`Restore requested from backup "${options.from}"`);
|
|
5868
6062
|
}));
|
|
5869
|
-
dbCmd.command("enable-public <name>").description("Enable public access for a database").action(withAuth({ spinnerText: "Enabling public access..." }, async (ctx, name) => {
|
|
6063
|
+
dbCmd.command("enable-public <name>").description("Enable public access for a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Enabling public access..." }, async (ctx, name, options) => {
|
|
5870
6064
|
const client = createDatabaseClient();
|
|
5871
6065
|
const { error: error2, response } = await client.POST("/databases/{databaseName}/enable-public", {
|
|
5872
6066
|
headers: ctx.auth,
|
|
@@ -5875,9 +6069,20 @@ function createDatabaseCommand() {
|
|
|
5875
6069
|
}
|
|
5876
6070
|
});
|
|
5877
6071
|
if (error2) throw mapApiError(response.status, error2);
|
|
6072
|
+
if (options.output === "json") {
|
|
6073
|
+
ctx.spinner.stop();
|
|
6074
|
+
outputJson({
|
|
6075
|
+
success: true,
|
|
6076
|
+
action: "enable-public",
|
|
6077
|
+
resource: "database",
|
|
6078
|
+
name,
|
|
6079
|
+
status: "enabled"
|
|
6080
|
+
});
|
|
6081
|
+
return;
|
|
6082
|
+
}
|
|
5878
6083
|
ctx.spinner.succeed(`Public access enabled for "${name}"`);
|
|
5879
6084
|
}));
|
|
5880
|
-
dbCmd.command("disable-public <name>").description("Disable public access for a database").action(withAuth({ spinnerText: "Disabling public access..." }, async (ctx, name) => {
|
|
6085
|
+
dbCmd.command("disable-public <name>").description("Disable public access for a database").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Disabling public access..." }, async (ctx, name, options) => {
|
|
5881
6086
|
const client = createDatabaseClient();
|
|
5882
6087
|
const { error: error2, response } = await client.POST("/databases/{databaseName}/disable-public", {
|
|
5883
6088
|
headers: ctx.auth,
|
|
@@ -5886,9 +6091,20 @@ function createDatabaseCommand() {
|
|
|
5886
6091
|
}
|
|
5887
6092
|
});
|
|
5888
6093
|
if (error2) throw mapApiError(response.status, error2);
|
|
6094
|
+
if (options.output === "json") {
|
|
6095
|
+
ctx.spinner.stop();
|
|
6096
|
+
outputJson({
|
|
6097
|
+
success: true,
|
|
6098
|
+
action: "disable-public",
|
|
6099
|
+
resource: "database",
|
|
6100
|
+
name,
|
|
6101
|
+
status: "disabled"
|
|
6102
|
+
});
|
|
6103
|
+
return;
|
|
6104
|
+
}
|
|
5889
6105
|
ctx.spinner.succeed(`Public access disabled for "${name}"`);
|
|
5890
6106
|
}));
|
|
5891
|
-
dbCmd.command("logs <podName>").description("Get parsed database logs for a pod").requiredOption("--db-type <type>", "Database type used by the log service").requiredOption("--log-type <type>", "Log type used by the log service").requiredOption("--log-path <path>", 'Log path to read. Use "log-files" first to discover valid paths').option("--page <page>", "Page number", "1").option("--page-size <pageSize>", "Page size", "200").option("-o, --output <format>", "Output format (
|
|
6107
|
+
dbCmd.command("logs <podName>").description("Get parsed database logs for a pod").requiredOption("--db-type <type>", "Database type used by the log service").requiredOption("--log-type <type>", "Log type used by the log service").requiredOption("--log-path <path>", 'Log path to read. Use "log-files" first to discover valid paths').option("--page <page>", "Page number", "1").option("--page-size <pageSize>", "Page size", "200").option("-o, --output <format>", "Output format (json|table|plain)", "json").action(withAuth({
|
|
5892
6108
|
spinnerText: "Loading logs..."
|
|
5893
6109
|
}, async (ctx, podName, options) => {
|
|
5894
6110
|
const client = createDatabaseClient();
|
|
@@ -5925,7 +6141,7 @@ function createDatabaseCommand() {
|
|
|
5925
6141
|
console.log(source_default.dim(`
|
|
5926
6142
|
page=${data.data.metadata.page} total=${data.data.metadata.total} hasMore=${String(data.data.metadata.hasMore)}`));
|
|
5927
6143
|
}));
|
|
5928
|
-
dbCmd.command("log-files <podName>").description("List database log files for a pod").requiredOption("--db-type <type>", "Database type used by the log service").requiredOption("--log-type <type>", "Log type used by the log service").option("-o, --output <format>", "Output format (json|table)", "
|
|
6144
|
+
dbCmd.command("log-files <podName>").description("List database log files for a pod").requiredOption("--db-type <type>", "Database type used by the log service").requiredOption("--log-type <type>", "Log type used by the log service").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({
|
|
5929
6145
|
spinnerText: "Loading log files..."
|
|
5930
6146
|
}, async (ctx, podName, options) => {
|
|
5931
6147
|
const client = createDatabaseClient();
|
|
@@ -6119,6 +6335,11 @@ function createTemplateCommand() {
|
|
|
6119
6335
|
body: body2
|
|
6120
6336
|
});
|
|
6121
6337
|
if (error3) throw mapApiError(response2.status, error3);
|
|
6338
|
+
if (deployOptions.output === "json") {
|
|
6339
|
+
ctx.spinner.stop();
|
|
6340
|
+
outputJson(data2);
|
|
6341
|
+
return;
|
|
6342
|
+
}
|
|
6122
6343
|
ctx.spinner.succeed(`Instance "${data2.name}" created successfully`);
|
|
6123
6344
|
printInstanceResult(data2, { template: catalogTemplate });
|
|
6124
6345
|
return;
|
|
@@ -6130,6 +6351,11 @@ function createTemplateCommand() {
|
|
|
6130
6351
|
body
|
|
6131
6352
|
});
|
|
6132
6353
|
if (error2) throw mapApiError(response.status, error2);
|
|
6354
|
+
if (deployOptions.output === "json") {
|
|
6355
|
+
ctx.spinner.stop();
|
|
6356
|
+
outputJson(data);
|
|
6357
|
+
return;
|
|
6358
|
+
}
|
|
6133
6359
|
if (deployOptions.dryRun) {
|
|
6134
6360
|
ctx.spinner.succeed("Raw template validation passed; no resources were created");
|
|
6135
6361
|
printInstanceResult(data, { raw: true, dryRun: true });
|
|
@@ -6138,7 +6364,7 @@ function createTemplateCommand() {
|
|
|
6138
6364
|
ctx.spinner.succeed(`Raw template deployed as "${data.name}"`);
|
|
6139
6365
|
printInstanceResult(data, { raw: true });
|
|
6140
6366
|
});
|
|
6141
|
-
tplCmd.command("list").description("List available templates").option("-c, --category <category>", "Filter by category").option("-l, --language <language>", "Language code (for example: en, zh)").option("-o, --output <format>", "Output format (json|table)", "
|
|
6367
|
+
tplCmd.command("list").description("List available templates").option("-c, --category <category>", "Filter by category").option("-l, --language <language>", "Language code (for example: en, zh)").option("-o, --output <format>", "Output format (json|table)", "json").action(withErrorHandling({ spinnerText: "Loading templates..." }, async (ctx, options) => {
|
|
6142
6368
|
const client = createTemplateClient();
|
|
6143
6369
|
const { data, error: error2, response } = await client.GET("/templates", {
|
|
6144
6370
|
params: { query: options.language ? { language: options.language } : {} }
|
|
@@ -6166,7 +6392,7 @@ function createTemplateCommand() {
|
|
|
6166
6392
|
}
|
|
6167
6393
|
outputTable(rows);
|
|
6168
6394
|
}));
|
|
6169
|
-
tplCmd.command("get <name>").alias("describe").description("Get template details").option("-l, --language <language>", "Language code (for example: en, zh)").option("-o, --output <format>", "Output format (json|table)", "
|
|
6395
|
+
tplCmd.command("get <name>").alias("describe").description("Get template details").option("-l, --language <language>", "Language code (for example: en, zh)").option("-o, --output <format>", "Output format (json|table)", "json").action(withErrorHandling({ spinnerText: "Loading template..." }, async (ctx, name, options) => {
|
|
6170
6396
|
const client = createTemplateClient();
|
|
6171
6397
|
const { data, error: error2, response } = await client.GET("/templates/{name}", {
|
|
6172
6398
|
params: {
|
|
@@ -6214,7 +6440,7 @@ function createTemplateCommand() {
|
|
|
6214
6440
|
outputTable(argRows);
|
|
6215
6441
|
}
|
|
6216
6442
|
}));
|
|
6217
|
-
tplCmd.command("delete <instance>").alias("rm").description("Delete a deployed template instance").action(withAuth({ spinnerText: "Deleting template instance..." }, async (ctx, instance) => {
|
|
6443
|
+
tplCmd.command("delete <instance>").alias("rm").description("Delete a deployed template instance").option("-o, --output <format>", "Output format (json|table)", "json").action(withAuth({ spinnerText: "Deleting template instance..." }, async (ctx, instance, options) => {
|
|
6218
6444
|
const client = createTemplateClient();
|
|
6219
6445
|
const { error: error2, response } = await client.DELETE("/templates/instances/{instanceName}", {
|
|
6220
6446
|
headers: ctx.auth,
|
|
@@ -6223,9 +6449,20 @@ function createTemplateCommand() {
|
|
|
6223
6449
|
}
|
|
6224
6450
|
});
|
|
6225
6451
|
if (error2) throw mapApiError(response.status, error2);
|
|
6452
|
+
if (options.output === "json") {
|
|
6453
|
+
ctx.spinner.stop();
|
|
6454
|
+
outputJson({
|
|
6455
|
+
success: true,
|
|
6456
|
+
action: "delete",
|
|
6457
|
+
resource: "template-instance",
|
|
6458
|
+
instance,
|
|
6459
|
+
status: "deleted"
|
|
6460
|
+
});
|
|
6461
|
+
return;
|
|
6462
|
+
}
|
|
6226
6463
|
ctx.spinner.succeed(`Instance "${instance}" deleted`);
|
|
6227
6464
|
}));
|
|
6228
|
-
tplCmd.command("deploy [template]").description("Deploy a template (from catalog or raw YAML)").option("--name <name>", "Instance name (required when deploying from catalog)").option("--file <path>", "Path to template YAML file").option("--yaml <yaml>", "Template YAML string").option("--set <KEY=VALUE...>", "Set template arguments", (val, prev) => [...prev, val], []).option("--dry-run", "Validate raw template YAML without creating resources").addHelpText("after", `
|
|
6465
|
+
tplCmd.command("deploy [template]").description("Deploy a template (from catalog or raw YAML)").option("--name <name>", "Instance name (required when deploying from catalog)").option("--file <path>", "Path to template YAML file").option("--yaml <yaml>", "Template YAML string").option("--set <KEY=VALUE...>", "Set template arguments", (val, prev) => [...prev, val], []).option("--dry-run", "Validate raw template YAML without creating resources").option("-o, --output <format>", "Output format (json|table)", "json").addHelpText("after", `
|
|
6229
6466
|
Examples:
|
|
6230
6467
|
Catalog:
|
|
6231
6468
|
sealos-cli template deploy perplexica --name my-app --set OPENAI_API_KEY=xxx
|
|
@@ -6247,7 +6484,7 @@ __name(createTemplateCommand, "createTemplateCommand");
|
|
|
6247
6484
|
// package.json
|
|
6248
6485
|
var package_default = {
|
|
6249
6486
|
name: "sealos-cli",
|
|
6250
|
-
version: "1.1.
|
|
6487
|
+
version: "1.1.2",
|
|
6251
6488
|
description: "Official CLI tool for Sealos Cloud - Manage auth, workspaces, devboxes, databases, and templates",
|
|
6252
6489
|
types: "dist/main.d.ts",
|
|
6253
6490
|
type: "module",
|