@bagdock/cli 0.1.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +580 -22
- package/dist/bagdock.js +875 -166
- package/package.json +14 -5
- package/skill-evals/bagdock-cli/evals.json +152 -0
- package/skills/bagdock-cli/SKILL.md +123 -0
- package/skills/bagdock-cli/references/auth.md +113 -0
- package/skills/bagdock-cli/references/deploy.md +91 -0
- package/skills/bagdock-cli/references/dev.md +45 -0
- package/skills/bagdock-cli/references/env.md +37 -0
- package/skills/bagdock-cli/references/error-codes.md +53 -0
package/dist/bagdock.js
CHANGED
|
@@ -2085,31 +2085,87 @@ var require_commander = __commonJS((exports) => {
|
|
|
2085
2085
|
import { homedir } from "os";
|
|
2086
2086
|
import { join } from "path";
|
|
2087
2087
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2088
|
+
function setProfileOverride(name) {
|
|
2089
|
+
profileOverride = name;
|
|
2090
|
+
}
|
|
2088
2091
|
function ensureConfigDir() {
|
|
2089
2092
|
if (!existsSync(CONFIG_DIR)) {
|
|
2090
2093
|
mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
2091
2094
|
}
|
|
2092
2095
|
}
|
|
2093
|
-
function
|
|
2096
|
+
function loadStore() {
|
|
2094
2097
|
try {
|
|
2095
|
-
if (!existsSync(CREDENTIALS_FILE))
|
|
2096
|
-
return
|
|
2097
|
-
|
|
2098
|
-
|
|
2098
|
+
if (!existsSync(CREDENTIALS_FILE)) {
|
|
2099
|
+
return { activeProfile: "default", profiles: {} };
|
|
2100
|
+
}
|
|
2101
|
+
const raw = JSON.parse(readFileSync(CREDENTIALS_FILE, "utf-8"));
|
|
2102
|
+
if (raw.accessToken && !raw.profiles) {
|
|
2103
|
+
const migrated = {
|
|
2104
|
+
activeProfile: "default",
|
|
2105
|
+
profiles: { default: raw }
|
|
2106
|
+
};
|
|
2107
|
+
saveStore(migrated);
|
|
2108
|
+
return migrated;
|
|
2109
|
+
}
|
|
2110
|
+
return raw;
|
|
2099
2111
|
} catch {
|
|
2100
|
-
return
|
|
2112
|
+
return { activeProfile: "default", profiles: {} };
|
|
2101
2113
|
}
|
|
2102
2114
|
}
|
|
2103
|
-
function
|
|
2115
|
+
function saveStore(store) {
|
|
2104
2116
|
ensureConfigDir();
|
|
2105
|
-
writeFileSync(CREDENTIALS_FILE, JSON.stringify(
|
|
2117
|
+
writeFileSync(CREDENTIALS_FILE, JSON.stringify(store, null, 2), { mode: 384 });
|
|
2118
|
+
}
|
|
2119
|
+
function resolveProfile() {
|
|
2120
|
+
if (profileOverride)
|
|
2121
|
+
return profileOverride;
|
|
2122
|
+
if (process.env.BAGDOCK_PROFILE)
|
|
2123
|
+
return process.env.BAGDOCK_PROFILE;
|
|
2124
|
+
return loadStore().activeProfile;
|
|
2125
|
+
}
|
|
2126
|
+
function loadCredentials() {
|
|
2127
|
+
const store = loadStore();
|
|
2128
|
+
const name = resolveProfile();
|
|
2129
|
+
return store.profiles[name] ?? null;
|
|
2130
|
+
}
|
|
2131
|
+
function saveCredentials(creds, profileName) {
|
|
2132
|
+
const store = loadStore();
|
|
2133
|
+
const name = profileName ?? resolveProfile();
|
|
2134
|
+
store.profiles[name] = creds;
|
|
2135
|
+
if (!store.activeProfile || Object.keys(store.profiles).length === 1) {
|
|
2136
|
+
store.activeProfile = name;
|
|
2137
|
+
}
|
|
2138
|
+
saveStore(store);
|
|
2106
2139
|
}
|
|
2107
2140
|
function clearCredentials() {
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2141
|
+
const store = loadStore();
|
|
2142
|
+
const name = resolveProfile();
|
|
2143
|
+
delete store.profiles[name];
|
|
2144
|
+
if (store.activeProfile === name) {
|
|
2145
|
+
const remaining = Object.keys(store.profiles);
|
|
2146
|
+
store.activeProfile = remaining[0] ?? "default";
|
|
2147
|
+
}
|
|
2148
|
+
saveStore(store);
|
|
2149
|
+
}
|
|
2150
|
+
function listProfiles() {
|
|
2151
|
+
const store = loadStore();
|
|
2152
|
+
return Object.entries(store.profiles).map(([name, creds]) => ({
|
|
2153
|
+
name,
|
|
2154
|
+
email: creds.email,
|
|
2155
|
+
operatorId: creds.operatorId,
|
|
2156
|
+
active: name === store.activeProfile
|
|
2157
|
+
}));
|
|
2158
|
+
}
|
|
2159
|
+
function switchProfile(name) {
|
|
2160
|
+
const store = loadStore();
|
|
2161
|
+
if (!store.profiles[name])
|
|
2162
|
+
return false;
|
|
2163
|
+
store.activeProfile = name;
|
|
2164
|
+
saveStore(store);
|
|
2165
|
+
return true;
|
|
2166
|
+
}
|
|
2167
|
+
function getActiveProfileName() {
|
|
2168
|
+
return resolveProfile();
|
|
2113
2169
|
}
|
|
2114
2170
|
function loadBagdockJson(dir) {
|
|
2115
2171
|
const file = join(dir, "bagdock.json");
|
|
@@ -2121,7 +2177,7 @@ function loadBagdockJson(dir) {
|
|
|
2121
2177
|
return null;
|
|
2122
2178
|
}
|
|
2123
2179
|
}
|
|
2124
|
-
var CONFIG_DIR, CREDENTIALS_FILE, API_BASE, DASHBOARD_BASE;
|
|
2180
|
+
var CONFIG_DIR, CREDENTIALS_FILE, API_BASE, DASHBOARD_BASE, profileOverride;
|
|
2125
2181
|
var init_config = __esm(() => {
|
|
2126
2182
|
CONFIG_DIR = join(homedir(), ".bagdock");
|
|
2127
2183
|
CREDENTIALS_FILE = join(CONFIG_DIR, "credentials.json");
|
|
@@ -2618,6 +2674,59 @@ var init_source = __esm(() => {
|
|
|
2618
2674
|
source_default = chalk;
|
|
2619
2675
|
});
|
|
2620
2676
|
|
|
2677
|
+
// src/output.ts
|
|
2678
|
+
function setOutputMode(opts) {
|
|
2679
|
+
quiet = !!opts.quiet;
|
|
2680
|
+
forceJson = !!opts.json || !!opts.quiet;
|
|
2681
|
+
}
|
|
2682
|
+
function isJsonMode() {
|
|
2683
|
+
return forceJson || !process.stdout.isTTY;
|
|
2684
|
+
}
|
|
2685
|
+
function isQuiet() {
|
|
2686
|
+
return quiet;
|
|
2687
|
+
}
|
|
2688
|
+
function outputSuccess(data) {
|
|
2689
|
+
if (isJsonMode()) {
|
|
2690
|
+
process.stdout.write(JSON.stringify(data, null, 2) + `
|
|
2691
|
+
`);
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
function outputError(code, message, details) {
|
|
2695
|
+
if (isJsonMode()) {
|
|
2696
|
+
const err = { error: { code, message } };
|
|
2697
|
+
if (details)
|
|
2698
|
+
err.error.details = details;
|
|
2699
|
+
process.stderr.write(JSON.stringify(err) + `
|
|
2700
|
+
`);
|
|
2701
|
+
process.exit(1);
|
|
2702
|
+
} else {
|
|
2703
|
+
console.error(source_default.red(`Error [${code}]:`), message);
|
|
2704
|
+
if (details)
|
|
2705
|
+
console.error(details);
|
|
2706
|
+
process.exit(1);
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
function outputList(objectType, data, hasMore) {
|
|
2710
|
+
if (isJsonMode()) {
|
|
2711
|
+
process.stdout.write(JSON.stringify({ object: "list", data, has_more: hasMore }, null, 2) + `
|
|
2712
|
+
`);
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
function status(message) {
|
|
2716
|
+
if (!isQuiet() && !isJsonMode()) {
|
|
2717
|
+
console.log(source_default.dim(message));
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
function success(message) {
|
|
2721
|
+
if (!isQuiet() && !isJsonMode()) {
|
|
2722
|
+
console.log(source_default.green(message));
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
var forceJson = false, quiet = false;
|
|
2726
|
+
var init_output = __esm(() => {
|
|
2727
|
+
init_source();
|
|
2728
|
+
});
|
|
2729
|
+
|
|
2621
2730
|
// node_modules/is-docker/index.js
|
|
2622
2731
|
import fs from "node:fs";
|
|
2623
2732
|
function hasDockerEnv() {
|
|
@@ -3158,13 +3267,367 @@ var init_open = __esm(() => {
|
|
|
3158
3267
|
open_default = open;
|
|
3159
3268
|
});
|
|
3160
3269
|
|
|
3270
|
+
// src/auth.ts
|
|
3271
|
+
function setApiKeyOverride(key) {
|
|
3272
|
+
apiKeyOverride = key;
|
|
3273
|
+
}
|
|
3274
|
+
function getAuthToken() {
|
|
3275
|
+
if (apiKeyOverride)
|
|
3276
|
+
return apiKeyOverride;
|
|
3277
|
+
if (process.env.BAGDOCK_API_KEY)
|
|
3278
|
+
return process.env.BAGDOCK_API_KEY;
|
|
3279
|
+
if (process.env.BAGDOCK_TOKEN)
|
|
3280
|
+
return process.env.BAGDOCK_TOKEN;
|
|
3281
|
+
const creds = loadCredentials();
|
|
3282
|
+
return creds?.accessToken ?? null;
|
|
3283
|
+
}
|
|
3284
|
+
function getAuthSource() {
|
|
3285
|
+
if (apiKeyOverride)
|
|
3286
|
+
return { token: apiKeyOverride, source: "flag" };
|
|
3287
|
+
if (process.env.BAGDOCK_API_KEY)
|
|
3288
|
+
return { token: process.env.BAGDOCK_API_KEY, source: "env (BAGDOCK_API_KEY)" };
|
|
3289
|
+
if (process.env.BAGDOCK_TOKEN)
|
|
3290
|
+
return { token: process.env.BAGDOCK_TOKEN, source: "env (BAGDOCK_TOKEN)" };
|
|
3291
|
+
const creds = loadCredentials();
|
|
3292
|
+
if (creds?.accessToken)
|
|
3293
|
+
return { token: creds.accessToken, source: `config (${getActiveProfileName()})` };
|
|
3294
|
+
return { token: null, source: "none" };
|
|
3295
|
+
}
|
|
3296
|
+
async function login() {
|
|
3297
|
+
const existing = loadCredentials();
|
|
3298
|
+
if (existing?.accessToken && existing.expiresAt && existing.expiresAt > Date.now()) {
|
|
3299
|
+
console.log(source_default.green("Already logged in as"), source_default.bold(existing.email ?? "unknown"));
|
|
3300
|
+
console.log("Run", source_default.cyan("bagdock logout"), "to sign out first.");
|
|
3301
|
+
return;
|
|
3302
|
+
}
|
|
3303
|
+
console.log(source_default.cyan(`
|
|
3304
|
+
Requesting device authorization...
|
|
3305
|
+
`));
|
|
3306
|
+
const deviceRes = await fetch(`${API_BASE}/oauth2/device/authorize`, {
|
|
3307
|
+
method: "POST",
|
|
3308
|
+
headers: { "Content-Type": "application/json" },
|
|
3309
|
+
body: JSON.stringify({ client_id: CLIENT_ID, scope: "developer:read developer:write" })
|
|
3310
|
+
});
|
|
3311
|
+
if (!deviceRes.ok) {
|
|
3312
|
+
const err = await deviceRes.text();
|
|
3313
|
+
console.log(source_default.red("Failed to start login:"), err);
|
|
3314
|
+
process.exit(1);
|
|
3315
|
+
}
|
|
3316
|
+
const device = await deviceRes.json();
|
|
3317
|
+
const pollInterval = (device.interval ?? 5) * 1000;
|
|
3318
|
+
console.log(` Visit ${source_default.bold(device.verification_uri)} and enter code:
|
|
3319
|
+
`);
|
|
3320
|
+
console.log(` ${source_default.bold.cyan(device.user_code)}
|
|
3321
|
+
`);
|
|
3322
|
+
const open2 = (await Promise.resolve().then(() => (init_open(), exports_open))).default;
|
|
3323
|
+
await open2(device.verification_uri_complete).catch(() => {});
|
|
3324
|
+
console.log(source_default.dim(" Waiting for authorization..."));
|
|
3325
|
+
const startedAt = Date.now();
|
|
3326
|
+
while (Date.now() - startedAt < MAX_POLL_DURATION_MS) {
|
|
3327
|
+
await sleep(pollInterval);
|
|
3328
|
+
const tokenRes = await fetch(`${API_BASE}/oauth2/token`, {
|
|
3329
|
+
method: "POST",
|
|
3330
|
+
headers: { "Content-Type": "application/json" },
|
|
3331
|
+
body: JSON.stringify({
|
|
3332
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
3333
|
+
client_id: CLIENT_ID,
|
|
3334
|
+
device_code: device.device_code
|
|
3335
|
+
})
|
|
3336
|
+
});
|
|
3337
|
+
if (tokenRes.ok) {
|
|
3338
|
+
const tokens = await tokenRes.json();
|
|
3339
|
+
saveCredentials({
|
|
3340
|
+
accessToken: tokens.access_token,
|
|
3341
|
+
refreshToken: tokens.refresh_token,
|
|
3342
|
+
expiresAt: tokens.expires_in ? Date.now() + tokens.expires_in * 1000 : undefined,
|
|
3343
|
+
email: tokens.email,
|
|
3344
|
+
operatorId: tokens.operator_id
|
|
3345
|
+
});
|
|
3346
|
+
console.log(source_default.green(`
|
|
3347
|
+
Logged in successfully!`));
|
|
3348
|
+
if (tokens.email)
|
|
3349
|
+
console.log(" Email:", source_default.bold(tokens.email));
|
|
3350
|
+
if (tokens.operator_id)
|
|
3351
|
+
console.log(" Operator:", source_default.bold(tokens.operator_id));
|
|
3352
|
+
console.log(" Profile:", source_default.bold(getActiveProfileName()));
|
|
3353
|
+
return;
|
|
3354
|
+
}
|
|
3355
|
+
const error = await tokenRes.json().catch(() => ({ error: "unknown" }));
|
|
3356
|
+
if (error.error === "authorization_pending")
|
|
3357
|
+
continue;
|
|
3358
|
+
if (error.error === "slow_down") {
|
|
3359
|
+
await sleep(pollInterval);
|
|
3360
|
+
continue;
|
|
3361
|
+
}
|
|
3362
|
+
if (error.error === "expired_token") {
|
|
3363
|
+
console.log(source_default.red(`
|
|
3364
|
+
Device code expired. Please try again.`));
|
|
3365
|
+
process.exit(1);
|
|
3366
|
+
}
|
|
3367
|
+
if (error.error === "access_denied") {
|
|
3368
|
+
console.log(source_default.red(`
|
|
3369
|
+
Authorization denied.`));
|
|
3370
|
+
process.exit(1);
|
|
3371
|
+
}
|
|
3372
|
+
console.log(source_default.red(`
|
|
3373
|
+
Login failed:`), error.error_description ?? error.error);
|
|
3374
|
+
process.exit(1);
|
|
3375
|
+
}
|
|
3376
|
+
console.log(source_default.red(`
|
|
3377
|
+
Login timed out. Please try again.`));
|
|
3378
|
+
process.exit(1);
|
|
3379
|
+
}
|
|
3380
|
+
async function logout() {
|
|
3381
|
+
clearCredentials();
|
|
3382
|
+
console.log(source_default.green(`Logged out of profile "${getActiveProfileName()}".`));
|
|
3383
|
+
}
|
|
3384
|
+
async function whoami() {
|
|
3385
|
+
const token = getAuthToken();
|
|
3386
|
+
if (!token) {
|
|
3387
|
+
console.log(source_default.yellow("Not logged in."), "Run", source_default.cyan("bagdock login"));
|
|
3388
|
+
process.exit(1);
|
|
3389
|
+
}
|
|
3390
|
+
try {
|
|
3391
|
+
const res = await fetch(`${API_BASE}/v1/auth/me`, {
|
|
3392
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
3393
|
+
});
|
|
3394
|
+
if (!res.ok) {
|
|
3395
|
+
console.log(source_default.red("Session expired or invalid."), "Run", source_default.cyan("bagdock login"));
|
|
3396
|
+
process.exit(1);
|
|
3397
|
+
}
|
|
3398
|
+
const user = await res.json();
|
|
3399
|
+
if (isJsonMode()) {
|
|
3400
|
+
outputSuccess({ ...user, profile: getActiveProfileName() });
|
|
3401
|
+
} else {
|
|
3402
|
+
console.log(source_default.green("Logged in as"), source_default.bold(user.email));
|
|
3403
|
+
if (user.operator_id)
|
|
3404
|
+
console.log("Operator:", source_default.bold(user.operator_id));
|
|
3405
|
+
if (user.name)
|
|
3406
|
+
console.log("Name:", user.name);
|
|
3407
|
+
console.log("Profile:", source_default.bold(getActiveProfileName()));
|
|
3408
|
+
}
|
|
3409
|
+
} catch (err) {
|
|
3410
|
+
console.log(source_default.red("Failed to reach API:"), err.message);
|
|
3411
|
+
process.exit(1);
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3414
|
+
async function authList() {
|
|
3415
|
+
const profiles = listProfiles();
|
|
3416
|
+
if (isJsonMode()) {
|
|
3417
|
+
outputSuccess({ profiles });
|
|
3418
|
+
return;
|
|
3419
|
+
}
|
|
3420
|
+
if (!profiles.length) {
|
|
3421
|
+
console.log(source_default.yellow(`
|
|
3422
|
+
No profiles found.`), "Run", source_default.cyan("bagdock login"), `to create one.
|
|
3423
|
+
`);
|
|
3424
|
+
return;
|
|
3425
|
+
}
|
|
3426
|
+
console.log();
|
|
3427
|
+
for (const p of profiles) {
|
|
3428
|
+
const marker = p.active ? source_default.green("* ") : " ";
|
|
3429
|
+
const label = p.active ? source_default.bold(p.name) : p.name;
|
|
3430
|
+
const email = p.email ? source_default.dim(` (${p.email})`) : "";
|
|
3431
|
+
const op = p.operatorId ? source_default.dim(` [${p.operatorId}]`) : "";
|
|
3432
|
+
console.log(` ${marker}${label}${email}${op}`);
|
|
3433
|
+
}
|
|
3434
|
+
console.log();
|
|
3435
|
+
}
|
|
3436
|
+
async function authSwitch(name) {
|
|
3437
|
+
const profiles = listProfiles();
|
|
3438
|
+
if (!profiles.length) {
|
|
3439
|
+
console.log(source_default.yellow("No profiles found."), "Run", source_default.cyan("bagdock login"), "first.");
|
|
3440
|
+
process.exit(1);
|
|
3441
|
+
}
|
|
3442
|
+
if (name) {
|
|
3443
|
+
if (switchProfile(name)) {
|
|
3444
|
+
if (isJsonMode()) {
|
|
3445
|
+
outputSuccess({ active_profile: name });
|
|
3446
|
+
} else {
|
|
3447
|
+
console.log(source_default.green(`Switched to profile "${name}".`));
|
|
3448
|
+
}
|
|
3449
|
+
} else {
|
|
3450
|
+
outputError("NOT_FOUND", `Profile "${name}" not found. Available: ${profiles.map((p) => p.name).join(", ")}`);
|
|
3451
|
+
}
|
|
3452
|
+
return;
|
|
3453
|
+
}
|
|
3454
|
+
if (!process.stdout.isTTY) {
|
|
3455
|
+
outputError("MISSING_PROFILE", "Pass a profile name in non-interactive mode: bagdock auth switch <name>");
|
|
3456
|
+
}
|
|
3457
|
+
console.log(source_default.cyan(`
|
|
3458
|
+
Available profiles:
|
|
3459
|
+
`));
|
|
3460
|
+
profiles.forEach((p, i) => {
|
|
3461
|
+
const marker = p.active ? source_default.green("* ") : " ";
|
|
3462
|
+
const email = p.email ? source_default.dim(` (${p.email})`) : "";
|
|
3463
|
+
console.log(` ${marker}${i + 1}. ${p.name}${email}`);
|
|
3464
|
+
});
|
|
3465
|
+
const readline = await import("readline");
|
|
3466
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
3467
|
+
const answer = await new Promise((resolve) => {
|
|
3468
|
+
rl.question(source_default.cyan(`
|
|
3469
|
+
Enter profile number or name: `), resolve);
|
|
3470
|
+
});
|
|
3471
|
+
rl.close();
|
|
3472
|
+
const idx = parseInt(answer, 10);
|
|
3473
|
+
const target = idx > 0 && idx <= profiles.length ? profiles[idx - 1].name : answer.trim();
|
|
3474
|
+
if (switchProfile(target)) {
|
|
3475
|
+
console.log(source_default.green(`
|
|
3476
|
+
Switched to profile "${target}".
|
|
3477
|
+
`));
|
|
3478
|
+
} else {
|
|
3479
|
+
console.log(source_default.red(`
|
|
3480
|
+
Profile "${target}" not found.
|
|
3481
|
+
`));
|
|
3482
|
+
process.exit(1);
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
function sleep(ms) {
|
|
3486
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3487
|
+
}
|
|
3488
|
+
var apiKeyOverride, CLIENT_ID = "bagdock-cli", MAX_POLL_DURATION_MS = 300000;
|
|
3489
|
+
var init_auth = __esm(() => {
|
|
3490
|
+
init_config();
|
|
3491
|
+
init_source();
|
|
3492
|
+
init_output();
|
|
3493
|
+
});
|
|
3494
|
+
|
|
3495
|
+
// src/doctor.ts
|
|
3496
|
+
var exports_doctor = {};
|
|
3497
|
+
__export(exports_doctor, {
|
|
3498
|
+
doctor: () => doctor
|
|
3499
|
+
});
|
|
3500
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
3501
|
+
import { join as join3, dirname } from "path";
|
|
3502
|
+
import { homedir as homedir2, platform as platform2 } from "os";
|
|
3503
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3504
|
+
function maskKey(key) {
|
|
3505
|
+
if (key.length <= 12)
|
|
3506
|
+
return key.slice(0, 4) + "...";
|
|
3507
|
+
return key.slice(0, 8) + "..." + key.slice(-4);
|
|
3508
|
+
}
|
|
3509
|
+
function getLocalVersion() {
|
|
3510
|
+
try {
|
|
3511
|
+
const pkgPath = join3(dirname(fileURLToPath2(import.meta.url)), "..", "package.json");
|
|
3512
|
+
const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
|
|
3513
|
+
return pkg.version ?? "unknown";
|
|
3514
|
+
} catch {
|
|
3515
|
+
return "unknown";
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3518
|
+
async function checkVersion() {
|
|
3519
|
+
const local = getLocalVersion();
|
|
3520
|
+
try {
|
|
3521
|
+
const res = await fetch("https://registry.npmjs.org/@bagdock/cli/latest", {
|
|
3522
|
+
signal: AbortSignal.timeout(5000)
|
|
3523
|
+
});
|
|
3524
|
+
if (res.ok) {
|
|
3525
|
+
const data = await res.json();
|
|
3526
|
+
if (data.version === local) {
|
|
3527
|
+
return { name: "CLI Version", status: "pass", message: `v${local} (latest)` };
|
|
3528
|
+
}
|
|
3529
|
+
return { name: "CLI Version", status: "warn", message: `v${local} (update available: v${data.version})` };
|
|
3530
|
+
}
|
|
3531
|
+
} catch {}
|
|
3532
|
+
return { name: "CLI Version", status: "pass", message: `v${local} (registry unreachable)` };
|
|
3533
|
+
}
|
|
3534
|
+
function checkAuth() {
|
|
3535
|
+
const { token, source } = getAuthSource();
|
|
3536
|
+
if (!token) {
|
|
3537
|
+
return { name: "API Key", status: "fail", message: "No API key found. Run `bagdock login` or set BAGDOCK_API_KEY." };
|
|
3538
|
+
}
|
|
3539
|
+
return { name: "API Key", status: "pass", message: `${maskKey(token)} (source: ${source})` };
|
|
3540
|
+
}
|
|
3541
|
+
function checkProjectConfig() {
|
|
3542
|
+
const config = loadBagdockJson(process.cwd());
|
|
3543
|
+
if (!config) {
|
|
3544
|
+
return { name: "Project Config", status: "warn", message: "No bagdock.json found in current directory" };
|
|
3545
|
+
}
|
|
3546
|
+
const issues = [];
|
|
3547
|
+
if (!config.slug)
|
|
3548
|
+
issues.push("missing slug");
|
|
3549
|
+
if (!config.type)
|
|
3550
|
+
issues.push("missing type");
|
|
3551
|
+
if (!config.main)
|
|
3552
|
+
issues.push("missing main");
|
|
3553
|
+
if (issues.length) {
|
|
3554
|
+
return { name: "Project Config", status: "warn", message: `bagdock.json has issues: ${issues.join(", ")}` };
|
|
3555
|
+
}
|
|
3556
|
+
return { name: "Project Config", status: "pass", message: `${config.slug} (${config.type}/${config.kind ?? config.category})` };
|
|
3557
|
+
}
|
|
3558
|
+
function checkAgents() {
|
|
3559
|
+
const detected = [];
|
|
3560
|
+
const home = homedir2();
|
|
3561
|
+
if (existsSync3(join3(home, ".cursor")))
|
|
3562
|
+
detected.push("Cursor");
|
|
3563
|
+
if (existsSync3(join3(home, ".windsurf")))
|
|
3564
|
+
detected.push("Windsurf");
|
|
3565
|
+
if (existsSync3(join3(home, "clawd", "skills")) || existsSync3(join3(home, ".codex")))
|
|
3566
|
+
detected.push("OpenClaw/Codex");
|
|
3567
|
+
const p = platform2();
|
|
3568
|
+
if (p === "darwin" && existsSync3(join3(home, "Library", "Application Support", "Claude", "claude_desktop_config.json"))) {
|
|
3569
|
+
detected.push("Claude Desktop");
|
|
3570
|
+
} else if (p === "win32" && existsSync3(join3(process.env.APPDATA ?? "", "Claude", "claude_desktop_config.json"))) {
|
|
3571
|
+
detected.push("Claude Desktop");
|
|
3572
|
+
} else if (p === "linux" && existsSync3(join3(home, ".config", "Claude", "claude_desktop_config.json"))) {
|
|
3573
|
+
detected.push("Claude Desktop");
|
|
3574
|
+
}
|
|
3575
|
+
if (existsSync3(join3(process.cwd(), ".vscode", "mcp.json")))
|
|
3576
|
+
detected.push("VS Code");
|
|
3577
|
+
if (!detected.length) {
|
|
3578
|
+
return { name: "AI Agents", status: "pass", message: "None detected" };
|
|
3579
|
+
}
|
|
3580
|
+
return { name: "AI Agents", status: "pass", message: `Detected: ${detected.join(", ")}` };
|
|
3581
|
+
}
|
|
3582
|
+
async function doctor() {
|
|
3583
|
+
const checks = [];
|
|
3584
|
+
if (isJsonMode()) {
|
|
3585
|
+
checks.push(await checkVersion());
|
|
3586
|
+
checks.push(checkAuth());
|
|
3587
|
+
checks.push(checkProjectConfig());
|
|
3588
|
+
checks.push(checkAgents());
|
|
3589
|
+
const ok = checks.every((c) => c.status !== "fail");
|
|
3590
|
+
outputSuccess({ ok, checks });
|
|
3591
|
+
return;
|
|
3592
|
+
}
|
|
3593
|
+
console.log(source_default.bold(`
|
|
3594
|
+
Bagdock Doctor
|
|
3595
|
+
`));
|
|
3596
|
+
process.stdout.write(" Checking CLI version...");
|
|
3597
|
+
const versionCheck = await checkVersion();
|
|
3598
|
+
checks.push(versionCheck);
|
|
3599
|
+
process.stdout.write(`\r ${ICON[versionCheck.status]} ${versionCheck.name}: ${versionCheck.message}
|
|
3600
|
+
`);
|
|
3601
|
+
const authCheck = checkAuth();
|
|
3602
|
+
checks.push(authCheck);
|
|
3603
|
+
console.log(` ${ICON[authCheck.status]} ${authCheck.name}: ${authCheck.message}`);
|
|
3604
|
+
const configCheck = checkProjectConfig();
|
|
3605
|
+
checks.push(configCheck);
|
|
3606
|
+
console.log(` ${ICON[configCheck.status]} ${configCheck.name}: ${configCheck.message}`);
|
|
3607
|
+
const agentCheck = checkAgents();
|
|
3608
|
+
checks.push(agentCheck);
|
|
3609
|
+
console.log(` ${ICON[agentCheck.status]} ${agentCheck.name}: ${agentCheck.message}`);
|
|
3610
|
+
console.log();
|
|
3611
|
+
const hasFail = checks.some((c) => c.status === "fail");
|
|
3612
|
+
if (hasFail)
|
|
3613
|
+
process.exit(1);
|
|
3614
|
+
}
|
|
3615
|
+
var ICON;
|
|
3616
|
+
var init_doctor = __esm(() => {
|
|
3617
|
+
init_source();
|
|
3618
|
+
init_auth();
|
|
3619
|
+
init_config();
|
|
3620
|
+
init_output();
|
|
3621
|
+
ICON = { pass: source_default.green("✔"), warn: source_default.yellow("!"), fail: source_default.red("✘") };
|
|
3622
|
+
});
|
|
3623
|
+
|
|
3161
3624
|
// src/dev.ts
|
|
3162
3625
|
var exports_dev = {};
|
|
3163
3626
|
__export(exports_dev, {
|
|
3164
3627
|
dev: () => dev
|
|
3165
3628
|
});
|
|
3166
|
-
import { existsSync as
|
|
3167
|
-
import { join as
|
|
3629
|
+
import { existsSync as existsSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
3630
|
+
import { join as join4 } from "path";
|
|
3168
3631
|
import { spawn } from "child_process";
|
|
3169
3632
|
async function dev(opts) {
|
|
3170
3633
|
const cwd = process.cwd();
|
|
@@ -3175,11 +3638,11 @@ async function dev(opts) {
|
|
|
3175
3638
|
}
|
|
3176
3639
|
const port = opts.port ?? "8787";
|
|
3177
3640
|
const wranglerToml = generateWranglerToml(config, port);
|
|
3178
|
-
const wranglerPath =
|
|
3641
|
+
const wranglerPath = join4(cwd, "wrangler.toml");
|
|
3179
3642
|
writeFileSync3(wranglerPath, wranglerToml);
|
|
3180
3643
|
console.log(source_default.green("Generated"), source_default.cyan("wrangler.toml"), source_default.green("from bagdock.json"));
|
|
3181
|
-
const devVarsPath =
|
|
3182
|
-
if (!
|
|
3644
|
+
const devVarsPath = join4(cwd, ".dev.vars");
|
|
3645
|
+
if (!existsSync4(devVarsPath) && config.env) {
|
|
3183
3646
|
const hint = Object.entries(config.env).map(([key, meta]) => `# ${meta.description ?? key}${meta.required ? " (required)" : ""}
|
|
3184
3647
|
${key}=`).join(`
|
|
3185
3648
|
`);
|
|
@@ -3240,8 +3703,8 @@ var exports_deploy = {};
|
|
|
3240
3703
|
__export(exports_deploy, {
|
|
3241
3704
|
deploy: () => deploy
|
|
3242
3705
|
});
|
|
3243
|
-
import { existsSync as
|
|
3244
|
-
import { join as
|
|
3706
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
3707
|
+
import { join as join5 } from "path";
|
|
3245
3708
|
import { execSync } from "child_process";
|
|
3246
3709
|
import { createInterface } from "readline";
|
|
3247
3710
|
async function deploy(opts) {
|
|
@@ -3251,9 +3714,9 @@ async function deploy(opts) {
|
|
|
3251
3714
|
console.error(source_default.red("No bagdock.json found. Run"), source_default.cyan("bagdock init"), source_default.red("first."));
|
|
3252
3715
|
process.exit(1);
|
|
3253
3716
|
}
|
|
3254
|
-
const
|
|
3255
|
-
if (!
|
|
3256
|
-
console.error(source_default.red("Not authenticated. Run"), source_default.cyan("bagdock login"), source_default.red("
|
|
3717
|
+
const token = getAuthToken();
|
|
3718
|
+
if (!token) {
|
|
3719
|
+
console.error(source_default.red("Not authenticated. Run"), source_default.cyan("bagdock login"), source_default.red("or set BAGDOCK_API_KEY."));
|
|
3257
3720
|
process.exit(1);
|
|
3258
3721
|
}
|
|
3259
3722
|
let environment = opts.env ?? "staging";
|
|
@@ -3282,8 +3745,8 @@ async function deploy(opts) {
|
|
|
3282
3745
|
console.log(source_default.cyan(`
|
|
3283
3746
|
Deploying ${config.slug}@${config.version} → ${envLabel}
|
|
3284
3747
|
`));
|
|
3285
|
-
const outDir =
|
|
3286
|
-
const outFile =
|
|
3748
|
+
const outDir = join5(cwd, ".bagdock");
|
|
3749
|
+
const outFile = join5(outDir, "worker.mjs");
|
|
3287
3750
|
console.log(source_default.dim(" Building worker bundle..."));
|
|
3288
3751
|
execSync(`mkdir -p ${outDir}`, { cwd });
|
|
3289
3752
|
try {
|
|
@@ -3299,11 +3762,11 @@ Deploying ${config.slug}@${config.version} → ${envLabel}
|
|
|
3299
3762
|
process.exit(1);
|
|
3300
3763
|
}
|
|
3301
3764
|
}
|
|
3302
|
-
if (!
|
|
3765
|
+
if (!existsSync5(outFile)) {
|
|
3303
3766
|
console.error(source_default.red(" Build output not found at"), outFile);
|
|
3304
3767
|
process.exit(1);
|
|
3305
3768
|
}
|
|
3306
|
-
const scriptContent =
|
|
3769
|
+
const scriptContent = readFileSync3(outFile);
|
|
3307
3770
|
const sizeKb = (scriptContent.length / 1024).toFixed(1);
|
|
3308
3771
|
console.log(source_default.dim(` Bundle size: ${sizeKb} KB`));
|
|
3309
3772
|
console.log(source_default.dim(" Uploading to Bagdock platform..."));
|
|
@@ -3318,7 +3781,7 @@ Deploying ${config.slug}@${config.version} → ${envLabel}
|
|
|
3318
3781
|
const res = await fetch(`${API_BASE}/api/v1/developer/apps/${config.slug}/deploy`, {
|
|
3319
3782
|
method: "POST",
|
|
3320
3783
|
headers: {
|
|
3321
|
-
Authorization: `Bearer ${
|
|
3784
|
+
Authorization: `Bearer ${token}`
|
|
3322
3785
|
},
|
|
3323
3786
|
body: formData
|
|
3324
3787
|
});
|
|
@@ -3374,6 +3837,7 @@ function confirm(prompt) {
|
|
|
3374
3837
|
var init_deploy = __esm(() => {
|
|
3375
3838
|
init_source();
|
|
3376
3839
|
init_config();
|
|
3840
|
+
init_auth();
|
|
3377
3841
|
});
|
|
3378
3842
|
|
|
3379
3843
|
// src/submit.ts
|
|
@@ -3387,9 +3851,9 @@ async function submit() {
|
|
|
3387
3851
|
console.error(source_default.red("No bagdock.json found. Run"), source_default.cyan("bagdock init"), source_default.red("first."));
|
|
3388
3852
|
process.exit(1);
|
|
3389
3853
|
}
|
|
3390
|
-
const
|
|
3391
|
-
if (!
|
|
3392
|
-
console.error(source_default.red("Not authenticated. Run"), source_default.cyan("bagdock login"), source_default.red("
|
|
3854
|
+
const token = getAuthToken();
|
|
3855
|
+
if (!token) {
|
|
3856
|
+
console.error(source_default.red("Not authenticated. Run"), source_default.cyan("bagdock login"), source_default.red("or set BAGDOCK_API_KEY."));
|
|
3393
3857
|
process.exit(1);
|
|
3394
3858
|
}
|
|
3395
3859
|
console.log(source_default.cyan(`
|
|
@@ -3399,7 +3863,7 @@ Submitting ${source_default.bold(config.slug)} for marketplace review...
|
|
|
3399
3863
|
const res = await fetch(`${API_BASE}/api/v1/developer/apps/${config.slug}/submit`, {
|
|
3400
3864
|
method: "POST",
|
|
3401
3865
|
headers: {
|
|
3402
|
-
Authorization: `Bearer ${
|
|
3866
|
+
Authorization: `Bearer ${token}`,
|
|
3403
3867
|
"Content-Type": "application/json"
|
|
3404
3868
|
}
|
|
3405
3869
|
});
|
|
@@ -3427,6 +3891,7 @@ Submitting ${source_default.bold(config.slug)} for marketplace review...
|
|
|
3427
3891
|
var init_submit = __esm(() => {
|
|
3428
3892
|
init_source();
|
|
3429
3893
|
init_config();
|
|
3894
|
+
init_auth();
|
|
3430
3895
|
});
|
|
3431
3896
|
|
|
3432
3897
|
// src/env-cmd.ts
|
|
@@ -3437,12 +3902,12 @@ __export(exports_env_cmd, {
|
|
|
3437
3902
|
envList: () => envList
|
|
3438
3903
|
});
|
|
3439
3904
|
function requireAuth() {
|
|
3440
|
-
const
|
|
3441
|
-
if (!
|
|
3442
|
-
console.error(source_default.red("Not authenticated. Run"), source_default.cyan("bagdock login"));
|
|
3905
|
+
const token = getAuthToken();
|
|
3906
|
+
if (!token) {
|
|
3907
|
+
console.error(source_default.red("Not authenticated. Run"), source_default.cyan("bagdock login"), source_default.red("or set BAGDOCK_API_KEY."));
|
|
3443
3908
|
process.exit(1);
|
|
3444
3909
|
}
|
|
3445
|
-
return
|
|
3910
|
+
return token;
|
|
3446
3911
|
}
|
|
3447
3912
|
function requireConfig() {
|
|
3448
3913
|
const config = loadBagdockJson(process.cwd());
|
|
@@ -3453,11 +3918,11 @@ function requireConfig() {
|
|
|
3453
3918
|
return config;
|
|
3454
3919
|
}
|
|
3455
3920
|
async function envList() {
|
|
3456
|
-
const
|
|
3921
|
+
const token = requireAuth();
|
|
3457
3922
|
const config = requireConfig();
|
|
3458
3923
|
try {
|
|
3459
3924
|
const res = await fetch(`${API_BASE}/v1/developer/apps/${config.slug}/env`, {
|
|
3460
|
-
headers: { Authorization: `Bearer ${
|
|
3925
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
3461
3926
|
});
|
|
3462
3927
|
if (!res.ok) {
|
|
3463
3928
|
console.error(source_default.red(`Failed to list env vars (${res.status})`));
|
|
@@ -3482,14 +3947,14 @@ Environment variables for ${config.slug}:
|
|
|
3482
3947
|
}
|
|
3483
3948
|
}
|
|
3484
3949
|
async function envSet(key, value) {
|
|
3485
|
-
const
|
|
3950
|
+
const token = requireAuth();
|
|
3486
3951
|
const config = requireConfig();
|
|
3487
3952
|
try {
|
|
3488
3953
|
const res = await fetch(`${API_BASE}/v1/developer/apps/${config.slug}/env`, {
|
|
3489
3954
|
method: "PUT",
|
|
3490
3955
|
headers: {
|
|
3491
3956
|
"Content-Type": "application/json",
|
|
3492
|
-
Authorization: `Bearer ${
|
|
3957
|
+
Authorization: `Bearer ${token}`
|
|
3493
3958
|
},
|
|
3494
3959
|
body: JSON.stringify({ key, value })
|
|
3495
3960
|
});
|
|
@@ -3505,12 +3970,12 @@ async function envSet(key, value) {
|
|
|
3505
3970
|
}
|
|
3506
3971
|
}
|
|
3507
3972
|
async function envRemove(key) {
|
|
3508
|
-
const
|
|
3973
|
+
const token = requireAuth();
|
|
3509
3974
|
const config = requireConfig();
|
|
3510
3975
|
try {
|
|
3511
3976
|
const res = await fetch(`${API_BASE}/v1/developer/apps/${config.slug}/env/${key}`, {
|
|
3512
3977
|
method: "DELETE",
|
|
3513
|
-
headers: { Authorization: `Bearer ${
|
|
3978
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
3514
3979
|
});
|
|
3515
3980
|
if (!res.ok) {
|
|
3516
3981
|
console.error(source_default.red(`Failed to remove ${key} (${res.status})`));
|
|
@@ -3525,146 +3990,339 @@ async function envRemove(key) {
|
|
|
3525
3990
|
var init_env_cmd = __esm(() => {
|
|
3526
3991
|
init_source();
|
|
3527
3992
|
init_config();
|
|
3993
|
+
init_auth();
|
|
3528
3994
|
});
|
|
3529
3995
|
|
|
3530
|
-
//
|
|
3531
|
-
var
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
Argument,
|
|
3542
|
-
Option,
|
|
3543
|
-
Help
|
|
3544
|
-
} = import__.default;
|
|
3545
|
-
|
|
3546
|
-
// src/auth.ts
|
|
3547
|
-
init_config();
|
|
3548
|
-
init_source();
|
|
3549
|
-
var CLIENT_ID = "bagdock-cli";
|
|
3550
|
-
var MAX_POLL_DURATION_MS = 300000;
|
|
3551
|
-
async function login() {
|
|
3552
|
-
const existing = loadCredentials();
|
|
3553
|
-
if (existing?.accessToken && existing.expiresAt && existing.expiresAt > Date.now()) {
|
|
3554
|
-
console.log(source_default.green("Already logged in as"), source_default.bold(existing.email ?? "unknown"));
|
|
3555
|
-
console.log("Run", source_default.cyan("bagdock logout"), "to sign out first.");
|
|
3556
|
-
return;
|
|
3996
|
+
// src/keys.ts
|
|
3997
|
+
var exports_keys = {};
|
|
3998
|
+
__export(exports_keys, {
|
|
3999
|
+
keysList: () => keysList,
|
|
4000
|
+
keysDelete: () => keysDelete,
|
|
4001
|
+
keysCreate: () => keysCreate
|
|
4002
|
+
});
|
|
4003
|
+
async function apiRequest(method, path2, body) {
|
|
4004
|
+
const token = getAuthToken();
|
|
4005
|
+
if (!token) {
|
|
4006
|
+
outputError("UNAUTHENTICATED", "Not logged in. Run `bagdock login` or set BAGDOCK_API_KEY.");
|
|
3557
4007
|
}
|
|
3558
|
-
|
|
3559
|
-
|
|
4008
|
+
const headers = { Authorization: `Bearer ${token}` };
|
|
4009
|
+
const init2 = { method, headers };
|
|
4010
|
+
if (body) {
|
|
4011
|
+
headers["Content-Type"] = "application/json";
|
|
4012
|
+
init2.body = JSON.stringify(body);
|
|
4013
|
+
}
|
|
4014
|
+
const res = await fetch(`${API_BASE}${path2}`, init2);
|
|
4015
|
+
return res;
|
|
4016
|
+
}
|
|
4017
|
+
async function keysCreate(opts) {
|
|
4018
|
+
status("Creating API key...");
|
|
4019
|
+
const res = await apiRequest("POST", "/api/v1/operator/api-keys", {
|
|
4020
|
+
name: opts.name,
|
|
4021
|
+
key_type: opts.type || "secret",
|
|
4022
|
+
key_category: opts.category || "standard",
|
|
4023
|
+
environment: opts.environment || "live",
|
|
4024
|
+
scopes: opts.scopes || []
|
|
4025
|
+
});
|
|
4026
|
+
if (!res.ok) {
|
|
4027
|
+
const err = await res.json().catch(() => ({ error: { message: res.statusText } }));
|
|
4028
|
+
outputError(err.error?.code || "API_ERROR", err.error?.message || `HTTP ${res.status}`);
|
|
4029
|
+
}
|
|
4030
|
+
const data = await res.json();
|
|
4031
|
+
if (isJsonMode()) {
|
|
4032
|
+
outputSuccess(data);
|
|
4033
|
+
} else {
|
|
4034
|
+
console.log(source_default.green(`
|
|
4035
|
+
API key created successfully!
|
|
3560
4036
|
`));
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
4037
|
+
console.log(` ${source_default.bold("Name:")} ${data.name}`);
|
|
4038
|
+
console.log(` ${source_default.bold("Key:")} ${source_default.yellow(data.key)}`);
|
|
4039
|
+
console.log(` ${source_default.bold("ID:")} ${data.id}`);
|
|
4040
|
+
console.log(` ${source_default.bold("Environment:")} ${data.environment}`);
|
|
4041
|
+
console.log(` ${source_default.bold("Type:")} ${data.key_type}`);
|
|
4042
|
+
console.log(` ${source_default.bold("Category:")} ${data.key_category}`);
|
|
4043
|
+
if (data.scopes?.length) {
|
|
4044
|
+
console.log(` ${source_default.bold("Scopes:")} ${data.scopes.join(", ")}`);
|
|
4045
|
+
}
|
|
4046
|
+
console.log();
|
|
4047
|
+
console.log(source_default.yellow(" Save this key — it will not be shown again."));
|
|
4048
|
+
console.log();
|
|
4049
|
+
}
|
|
4050
|
+
}
|
|
4051
|
+
async function keysList(opts) {
|
|
4052
|
+
status("Fetching API keys...");
|
|
4053
|
+
let path2 = "/api/v1/operator/api-keys";
|
|
4054
|
+
if (opts.environment)
|
|
4055
|
+
path2 += `?environment=${opts.environment}`;
|
|
4056
|
+
const res = await apiRequest("GET", path2);
|
|
4057
|
+
if (!res.ok) {
|
|
4058
|
+
const err = await res.json().catch(() => ({ error: { message: res.statusText } }));
|
|
4059
|
+
outputError(err.error?.code || "API_ERROR", err.error?.message || `HTTP ${res.status}`);
|
|
4060
|
+
}
|
|
4061
|
+
const result = await res.json();
|
|
4062
|
+
if (isJsonMode()) {
|
|
4063
|
+
outputList("api_key", result.data, result.has_more);
|
|
4064
|
+
} else {
|
|
4065
|
+
if (!result.data.length) {
|
|
4066
|
+
console.log(source_default.yellow(`
|
|
4067
|
+
No API keys found.
|
|
4068
|
+
`));
|
|
4069
|
+
return;
|
|
4070
|
+
}
|
|
4071
|
+
console.log();
|
|
4072
|
+
for (const key of result.data) {
|
|
4073
|
+
const usedAt = key.last_used_at ? new Date(key.last_used_at).toLocaleDateString() : "never";
|
|
4074
|
+
console.log(` ${source_default.bold(key.name)}`);
|
|
4075
|
+
console.log(` ${source_default.dim("Prefix:")} ${key.key_prefix}... ${source_default.dim("Env:")} ${key.environment} ${source_default.dim("Last used:")} ${usedAt}`);
|
|
4076
|
+
console.log(` ${source_default.dim("ID:")} ${key.id} ${source_default.dim("Category:")} ${key.key_category}`);
|
|
4077
|
+
console.log();
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
async function keysDelete(id, opts) {
|
|
4082
|
+
if (!opts.yes && !process.stdout.isTTY) {
|
|
4083
|
+
outputError("CONFIRMATION_REQUIRED", "Pass --yes to confirm deletion in non-interactive mode.");
|
|
4084
|
+
}
|
|
4085
|
+
status(`Revoking API key ${id}...`);
|
|
4086
|
+
const res = await apiRequest("DELETE", `/api/v1/operator/api-keys/${id}`, {
|
|
4087
|
+
reason: opts.reason
|
|
3565
4088
|
});
|
|
3566
|
-
if (!
|
|
3567
|
-
const err = await
|
|
3568
|
-
|
|
3569
|
-
process.exit(1);
|
|
4089
|
+
if (!res.ok) {
|
|
4090
|
+
const err = await res.json().catch(() => ({ error: { message: res.statusText } }));
|
|
4091
|
+
outputError(err.error?.code || "API_ERROR", err.error?.message || `HTTP ${res.status}`);
|
|
3570
4092
|
}
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
4093
|
+
if (isJsonMode()) {
|
|
4094
|
+
outputSuccess({ id, status: "revoked" });
|
|
4095
|
+
} else {
|
|
4096
|
+
success(`
|
|
4097
|
+
API key ${id} revoked.
|
|
3574
4098
|
`);
|
|
3575
|
-
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
var init_keys = __esm(() => {
|
|
4102
|
+
init_source();
|
|
4103
|
+
init_config();
|
|
4104
|
+
init_auth();
|
|
4105
|
+
init_output();
|
|
4106
|
+
});
|
|
4107
|
+
|
|
4108
|
+
// src/apps.ts
|
|
4109
|
+
var exports_apps = {};
|
|
4110
|
+
__export(exports_apps, {
|
|
4111
|
+
appsList: () => appsList,
|
|
4112
|
+
appsGet: () => appsGet
|
|
4113
|
+
});
|
|
4114
|
+
async function apiRequest2(method, path2) {
|
|
4115
|
+
const token = getAuthToken();
|
|
4116
|
+
if (!token) {
|
|
4117
|
+
outputError("UNAUTHENTICATED", "Not logged in. Run `bagdock login` or set BAGDOCK_API_KEY.");
|
|
4118
|
+
}
|
|
4119
|
+
return fetch(`${API_BASE}${path2}`, {
|
|
4120
|
+
method,
|
|
4121
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
4122
|
+
});
|
|
4123
|
+
}
|
|
4124
|
+
async function appsList() {
|
|
4125
|
+
status("Fetching apps...");
|
|
4126
|
+
const res = await apiRequest2("GET", "/api/v1/developer/apps");
|
|
4127
|
+
if (!res.ok) {
|
|
4128
|
+
const err = await res.json().catch(() => ({ error: { message: res.statusText } }));
|
|
4129
|
+
outputError(err.error?.code || "API_ERROR", err.error?.message || `HTTP ${res.status}`);
|
|
4130
|
+
}
|
|
4131
|
+
const result = await res.json();
|
|
4132
|
+
if (isJsonMode()) {
|
|
4133
|
+
outputList("app", result.data, false);
|
|
4134
|
+
} else {
|
|
4135
|
+
if (!result.data.length) {
|
|
4136
|
+
console.log(source_default.yellow(`
|
|
4137
|
+
No apps found. Create one with`), source_default.cyan("bagdock init"), `
|
|
3576
4138
|
`);
|
|
3577
|
-
const open2 = (await Promise.resolve().then(() => (init_open(), exports_open))).default;
|
|
3578
|
-
await open2(device.verification_uri_complete).catch(() => {});
|
|
3579
|
-
console.log(source_default.dim(" Waiting for authorization..."));
|
|
3580
|
-
const startedAt = Date.now();
|
|
3581
|
-
while (Date.now() - startedAt < MAX_POLL_DURATION_MS) {
|
|
3582
|
-
await sleep(pollInterval);
|
|
3583
|
-
const tokenRes = await fetch(`${API_BASE}/oauth2/token`, {
|
|
3584
|
-
method: "POST",
|
|
3585
|
-
headers: { "Content-Type": "application/json" },
|
|
3586
|
-
body: JSON.stringify({
|
|
3587
|
-
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
3588
|
-
client_id: CLIENT_ID,
|
|
3589
|
-
device_code: device.device_code
|
|
3590
|
-
})
|
|
3591
|
-
});
|
|
3592
|
-
if (tokenRes.ok) {
|
|
3593
|
-
const tokens = await tokenRes.json();
|
|
3594
|
-
saveCredentials({
|
|
3595
|
-
accessToken: tokens.access_token,
|
|
3596
|
-
refreshToken: tokens.refresh_token,
|
|
3597
|
-
expiresAt: tokens.expires_in ? Date.now() + tokens.expires_in * 1000 : undefined,
|
|
3598
|
-
email: tokens.email,
|
|
3599
|
-
operatorId: tokens.operator_id
|
|
3600
|
-
});
|
|
3601
|
-
console.log(source_default.green(`
|
|
3602
|
-
Logged in successfully!`));
|
|
3603
|
-
if (tokens.email)
|
|
3604
|
-
console.log(" Email:", source_default.bold(tokens.email));
|
|
3605
|
-
if (tokens.operator_id)
|
|
3606
|
-
console.log(" Operator:", source_default.bold(tokens.operator_id));
|
|
3607
4139
|
return;
|
|
3608
4140
|
}
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
}
|
|
3617
|
-
|
|
3618
|
-
console.log(
|
|
3619
|
-
Device code expired. Please try again.`));
|
|
3620
|
-
process.exit(1);
|
|
3621
|
-
}
|
|
3622
|
-
if (error.error === "access_denied") {
|
|
3623
|
-
console.log(source_default.red(`
|
|
3624
|
-
Authorization denied.`));
|
|
3625
|
-
process.exit(1);
|
|
4141
|
+
console.log();
|
|
4142
|
+
for (const app of result.data) {
|
|
4143
|
+
const status2 = app.is_active ? source_default.green("active") : source_default.dim("inactive");
|
|
4144
|
+
const review = app.review_status ? source_default.dim(`[${app.review_status}]`) : "";
|
|
4145
|
+
console.log(` ${source_default.bold(app.name)} ${source_default.dim(`(${app.slug})`)} ${status2} ${review}`);
|
|
4146
|
+
console.log(` ${source_default.dim("Type:")} ${app.type}/${app.category} ${source_default.dim("Version:")} ${app.version}`);
|
|
4147
|
+
if (app.worker_url) {
|
|
4148
|
+
console.log(` ${source_default.dim("URL:")} ${app.worker_url}`);
|
|
4149
|
+
}
|
|
4150
|
+
console.log();
|
|
3626
4151
|
}
|
|
3627
|
-
console.log(source_default.red(`
|
|
3628
|
-
Login failed:`), error.error_description ?? error.error);
|
|
3629
|
-
process.exit(1);
|
|
3630
4152
|
}
|
|
3631
|
-
console.log(source_default.red(`
|
|
3632
|
-
Login timed out. Please try again.`));
|
|
3633
|
-
process.exit(1);
|
|
3634
4153
|
}
|
|
3635
|
-
async function
|
|
3636
|
-
|
|
3637
|
-
|
|
4154
|
+
async function appsGet(slug) {
|
|
4155
|
+
status(`Fetching app ${slug}...`);
|
|
4156
|
+
const res = await apiRequest2("GET", `/api/v1/developer/apps/${slug}`);
|
|
4157
|
+
if (!res.ok) {
|
|
4158
|
+
if (res.status === 404) {
|
|
4159
|
+
outputError("NOT_FOUND", `App "${slug}" not found`);
|
|
4160
|
+
}
|
|
4161
|
+
const err = await res.json().catch(() => ({ error: { message: res.statusText } }));
|
|
4162
|
+
outputError(err.error?.code || "API_ERROR", err.error?.message || `HTTP ${res.status}`);
|
|
4163
|
+
}
|
|
4164
|
+
const result = await res.json();
|
|
4165
|
+
const app = result.data;
|
|
4166
|
+
if (isJsonMode()) {
|
|
4167
|
+
outputSuccess(app);
|
|
4168
|
+
} else {
|
|
4169
|
+
console.log();
|
|
4170
|
+
console.log(` ${source_default.bold(app.name)} ${source_default.dim(`(${app.slug})`)}`);
|
|
4171
|
+
console.log(` ${source_default.dim("ID:")} ${app.id}`);
|
|
4172
|
+
console.log(` ${source_default.dim("Type:")} ${app.type}`);
|
|
4173
|
+
console.log(` ${source_default.dim("Category:")} ${app.category}`);
|
|
4174
|
+
console.log(` ${source_default.dim("Kind:")} ${app.kind ?? "-"}`);
|
|
4175
|
+
console.log(` ${source_default.dim("Version:")} ${app.version}`);
|
|
4176
|
+
console.log(` ${source_default.dim("Visibility:")} ${app.visibility}`);
|
|
4177
|
+
console.log(` ${source_default.dim("Maintainer:")} ${app.maintainer}`);
|
|
4178
|
+
console.log(` ${source_default.dim("Review:")} ${app.review_status ?? "draft"}`);
|
|
4179
|
+
console.log(` ${source_default.dim("Active:")} ${app.is_active ? "yes" : "no"}`);
|
|
4180
|
+
if (app.worker_url) {
|
|
4181
|
+
console.log(` ${source_default.dim("Worker URL:")} ${app.worker_url}`);
|
|
4182
|
+
}
|
|
4183
|
+
console.log(` ${source_default.dim("Created:")} ${app.created_at}`);
|
|
4184
|
+
console.log(` ${source_default.dim("Updated:")} ${app.updated_at}`);
|
|
4185
|
+
console.log();
|
|
4186
|
+
}
|
|
3638
4187
|
}
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
4188
|
+
var init_apps = __esm(() => {
|
|
4189
|
+
init_source();
|
|
4190
|
+
init_config();
|
|
4191
|
+
init_auth();
|
|
4192
|
+
init_output();
|
|
4193
|
+
});
|
|
4194
|
+
|
|
4195
|
+
// src/logs.ts
|
|
4196
|
+
var exports_logs = {};
|
|
4197
|
+
__export(exports_logs, {
|
|
4198
|
+
logsTail: () => logsTail,
|
|
4199
|
+
logsList: () => logsList,
|
|
4200
|
+
logsGet: () => logsGet
|
|
4201
|
+
});
|
|
4202
|
+
async function apiRequest3(method, path2) {
|
|
4203
|
+
const token = getAuthToken();
|
|
4204
|
+
if (!token) {
|
|
4205
|
+
outputError("UNAUTHENTICATED", "Not logged in. Run `bagdock login` or set BAGDOCK_API_KEY.");
|
|
3645
4206
|
}
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
4207
|
+
return fetch(`${API_BASE}${path2}`, {
|
|
4208
|
+
method,
|
|
4209
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
4210
|
+
});
|
|
4211
|
+
}
|
|
4212
|
+
function resolveSlug(slug) {
|
|
4213
|
+
if (slug)
|
|
4214
|
+
return slug;
|
|
4215
|
+
const config = loadBagdockJson(process.cwd());
|
|
4216
|
+
if (config?.slug)
|
|
4217
|
+
return config.slug;
|
|
4218
|
+
outputError("MISSING_CONFIG", "No slug specified and no bagdock.json found. Pass --app <slug> or run from a project directory.");
|
|
4219
|
+
return "";
|
|
4220
|
+
}
|
|
4221
|
+
async function logsList(opts) {
|
|
4222
|
+
const slug = resolveSlug(opts.app);
|
|
4223
|
+
const limit = opts.limit || "50";
|
|
4224
|
+
status(`Fetching logs for ${slug}...`);
|
|
4225
|
+
const res = await apiRequest3("GET", `/api/v1/developer/apps/${slug}/logs?limit=${limit}`);
|
|
4226
|
+
if (!res.ok) {
|
|
4227
|
+
if (res.status === 404) {
|
|
4228
|
+
outputError("NOT_FOUND", `App "${slug}" not found or no logs available`);
|
|
4229
|
+
}
|
|
4230
|
+
const err = await res.json().catch(() => ({ error: { message: res.statusText } }));
|
|
4231
|
+
outputError(err.error?.code || "API_ERROR", err.error?.message || `HTTP ${res.status}`);
|
|
4232
|
+
}
|
|
4233
|
+
const result = await res.json();
|
|
4234
|
+
if (isJsonMode()) {
|
|
4235
|
+
outputList("log_entry", result.data, false);
|
|
4236
|
+
} else {
|
|
4237
|
+
if (!result.data?.length) {
|
|
4238
|
+
console.log(source_default.yellow(`
|
|
4239
|
+
No logs found for ${slug}.
|
|
4240
|
+
`));
|
|
4241
|
+
return;
|
|
3653
4242
|
}
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
console.log(source_default.red("Failed to reach API:"), err.message);
|
|
3662
|
-
process.exit(1);
|
|
4243
|
+
console.log();
|
|
4244
|
+
for (const entry of result.data) {
|
|
4245
|
+
const ts = source_default.dim(new Date(entry.timestamp).toISOString());
|
|
4246
|
+
const level = entry.level === "error" ? source_default.red(entry.level) : source_default.dim(entry.level);
|
|
4247
|
+
console.log(` ${ts} ${level} ${entry.message}`);
|
|
4248
|
+
}
|
|
4249
|
+
console.log();
|
|
3663
4250
|
}
|
|
3664
4251
|
}
|
|
3665
|
-
function
|
|
3666
|
-
|
|
4252
|
+
async function logsGet(id, opts) {
|
|
4253
|
+
const slug = resolveSlug(opts.app);
|
|
4254
|
+
status(`Fetching log entry ${id}...`);
|
|
4255
|
+
const res = await apiRequest3("GET", `/api/v1/developer/apps/${slug}/logs/${id}`);
|
|
4256
|
+
if (!res.ok) {
|
|
4257
|
+
const err = await res.json().catch(() => ({ error: { message: res.statusText } }));
|
|
4258
|
+
outputError(err.error?.code || "API_ERROR", err.error?.message || `HTTP ${res.status}`);
|
|
4259
|
+
}
|
|
4260
|
+
const data = await res.json();
|
|
4261
|
+
if (isJsonMode()) {
|
|
4262
|
+
outputSuccess(data);
|
|
4263
|
+
} else {
|
|
4264
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4265
|
+
}
|
|
3667
4266
|
}
|
|
4267
|
+
async function logsTail(opts) {
|
|
4268
|
+
const slug = resolveSlug(opts.app);
|
|
4269
|
+
if (isJsonMode()) {
|
|
4270
|
+
outputError("UNSUPPORTED", "Log tailing is not supported in JSON mode. Use `logs list` instead.");
|
|
4271
|
+
}
|
|
4272
|
+
console.log(source_default.cyan(`
|
|
4273
|
+
Tailing logs for ${slug}... (Ctrl+C to stop)
|
|
4274
|
+
`));
|
|
4275
|
+
let lastTimestamp = new Date().toISOString();
|
|
4276
|
+
const poll = async () => {
|
|
4277
|
+
try {
|
|
4278
|
+
const res = await apiRequest3("GET", `/api/v1/developer/apps/${slug}/logs?since=${encodeURIComponent(lastTimestamp)}&limit=100`);
|
|
4279
|
+
if (res.ok) {
|
|
4280
|
+
const result = await res.json();
|
|
4281
|
+
for (const entry of result.data || []) {
|
|
4282
|
+
const ts = source_default.dim(new Date(entry.timestamp).toISOString());
|
|
4283
|
+
const level = entry.level === "error" ? source_default.red(entry.level) : source_default.dim(entry.level);
|
|
4284
|
+
console.log(` ${ts} ${level} ${entry.message}`);
|
|
4285
|
+
lastTimestamp = entry.timestamp;
|
|
4286
|
+
}
|
|
4287
|
+
}
|
|
4288
|
+
} catch {}
|
|
4289
|
+
};
|
|
4290
|
+
const interval = setInterval(poll, 2000);
|
|
4291
|
+
await poll();
|
|
4292
|
+
process.on("SIGINT", () => {
|
|
4293
|
+
clearInterval(interval);
|
|
4294
|
+
console.log(source_default.dim(`
|
|
4295
|
+
Stopped tailing.
|
|
4296
|
+
`));
|
|
4297
|
+
process.exit(0);
|
|
4298
|
+
});
|
|
4299
|
+
await new Promise(() => {});
|
|
4300
|
+
}
|
|
4301
|
+
var init_logs = __esm(() => {
|
|
4302
|
+
init_source();
|
|
4303
|
+
init_config();
|
|
4304
|
+
init_auth();
|
|
4305
|
+
init_output();
|
|
4306
|
+
});
|
|
4307
|
+
|
|
4308
|
+
// node_modules/commander/esm.mjs
|
|
4309
|
+
var import__ = __toESM(require_commander(), 1);
|
|
4310
|
+
var {
|
|
4311
|
+
program,
|
|
4312
|
+
createCommand,
|
|
4313
|
+
createArgument,
|
|
4314
|
+
createOption,
|
|
4315
|
+
CommanderError,
|
|
4316
|
+
InvalidArgumentError,
|
|
4317
|
+
InvalidOptionArgumentError,
|
|
4318
|
+
Command,
|
|
4319
|
+
Argument,
|
|
4320
|
+
Option,
|
|
4321
|
+
Help
|
|
4322
|
+
} = import__.default;
|
|
4323
|
+
|
|
4324
|
+
// bin/bagdock.ts
|
|
4325
|
+
init_auth();
|
|
3668
4326
|
|
|
3669
4327
|
// src/init.ts
|
|
3670
4328
|
init_source();
|
|
@@ -3914,17 +4572,33 @@ function toPascalCase(s) {
|
|
|
3914
4572
|
}
|
|
3915
4573
|
|
|
3916
4574
|
// bin/bagdock.ts
|
|
4575
|
+
init_output();
|
|
4576
|
+
init_config();
|
|
3917
4577
|
var program2 = new Command;
|
|
3918
|
-
program2.name("bagdock").description("Bagdock developer CLI").version("0.
|
|
4578
|
+
program2.name("bagdock").description("Bagdock developer CLI — built for humans, AI agents, and CI/CD pipelines").version("0.3.0").option("--json", "Force JSON output (auto-enabled in non-TTY)").option("-q, --quiet", "Suppress status messages (implies --json)").option("--api-key <key>", "API key to use for this invocation").option("-p, --profile <name>", "Profile to use (overrides BAGDOCK_PROFILE)").hook("preAction", (_thisCommand, actionCommand) => {
|
|
4579
|
+
const opts = program2.opts();
|
|
4580
|
+
setOutputMode({ json: opts.json, quiet: opts.quiet });
|
|
4581
|
+
if (opts.apiKey)
|
|
4582
|
+
setApiKeyOverride(opts.apiKey);
|
|
4583
|
+
if (opts.profile)
|
|
4584
|
+
setProfileOverride(opts.profile);
|
|
4585
|
+
});
|
|
3919
4586
|
program2.command("login").description("Authenticate with Bagdock (opens browser)").action(login);
|
|
3920
4587
|
program2.command("logout").description("Clear stored credentials").action(logout);
|
|
3921
4588
|
program2.command("whoami").description("Show current authenticated user").action(whoami);
|
|
4589
|
+
var authCmd = program2.command("auth").description("Manage authentication profiles");
|
|
4590
|
+
authCmd.command("list").description("List all stored profiles").action(authList);
|
|
4591
|
+
authCmd.command("switch [name]").description("Switch active profile").action(async (name) => authSwitch(name));
|
|
4592
|
+
program2.command("doctor").description("Run environment diagnostics").action(async () => {
|
|
4593
|
+
const { doctor: doctor2 } = await Promise.resolve().then(() => (init_doctor(), exports_doctor));
|
|
4594
|
+
await doctor2();
|
|
4595
|
+
});
|
|
3922
4596
|
program2.command("init [dir]").description("Scaffold a new project with bagdock.json").option("-t, --type <type>", "Project type (edge, app)").option("-k, --kind <kind>", "Project kind (adapter, comms, webhook, ui-extension, microfrontend)").option("-c, --category <category>", "Category").option("-s, --slug <slug>", "Unique project slug").option("-n, --name <name>", "Display name").action((dir, opts) => init(dir ?? ".", opts));
|
|
3923
4597
|
program2.command("dev").description("Start local dev server").option("-p, --port <port>", "Local dev port", "8787").action(async (opts) => {
|
|
3924
4598
|
const { dev: dev2 } = await Promise.resolve().then(() => (init_dev(), exports_dev));
|
|
3925
4599
|
await dev2(opts);
|
|
3926
4600
|
});
|
|
3927
|
-
program2.command("deploy").description("Build locally and deploy via Bagdock API
|
|
4601
|
+
program2.command("deploy").description("Build locally and deploy via Bagdock API").option("--env <environment>", "Target environment (preview, staging, production)", "staging").option("--preview", "Deploy an ephemeral preview ({slug}-{hash}.pre.bdok.dev)").option("--production", "Deploy to production ({slug}.bdok.dev)").option("-y, --yes", "Skip confirmation prompts").action(async (opts) => {
|
|
3928
4602
|
const { deploy: deploy2 } = await Promise.resolve().then(() => (init_deploy(), exports_deploy));
|
|
3929
4603
|
await deploy2(opts);
|
|
3930
4604
|
});
|
|
@@ -3945,4 +4619,39 @@ envCmd.command("remove <key>").description("Remove an environment variable").act
|
|
|
3945
4619
|
const { envRemove: envRemove2 } = await Promise.resolve().then(() => (init_env_cmd(), exports_env_cmd));
|
|
3946
4620
|
await envRemove2(key);
|
|
3947
4621
|
});
|
|
4622
|
+
var keysCmd = program2.command("keys").description("Manage operator API keys");
|
|
4623
|
+
keysCmd.command("create").description("Create a new API key (raw key shown once)").requiredOption("--name <name>", "Key name").option("--type <type>", "Key type (secret, publishable)", "secret").option("--category <category>", "Key category (standard, restricted, personal)", "standard").option("--environment <env>", "Environment (live, test)", "live").option("--scopes <scopes...>", "Permission scopes").action(async (opts) => {
|
|
4624
|
+
const { keysCreate: keysCreate2 } = await Promise.resolve().then(() => (init_keys(), exports_keys));
|
|
4625
|
+
await keysCreate2(opts);
|
|
4626
|
+
});
|
|
4627
|
+
keysCmd.command("list").description("List API keys").option("--environment <env>", "Filter by environment (live, test)").action(async (opts) => {
|
|
4628
|
+
const { keysList: keysList2 } = await Promise.resolve().then(() => (init_keys(), exports_keys));
|
|
4629
|
+
await keysList2(opts);
|
|
4630
|
+
});
|
|
4631
|
+
keysCmd.command("delete <id>").description("Revoke an API key").option("-y, --yes", "Skip confirmation (required in non-TTY)").option("--reason <reason>", "Revocation reason").action(async (id, opts) => {
|
|
4632
|
+
const { keysDelete: keysDelete2 } = await Promise.resolve().then(() => (init_keys(), exports_keys));
|
|
4633
|
+
await keysDelete2(id, opts);
|
|
4634
|
+
});
|
|
4635
|
+
var appsCmd = program2.command("apps").description("List and inspect deployed apps and edges");
|
|
4636
|
+
appsCmd.command("list").description("List all apps for the authenticated operator").action(async () => {
|
|
4637
|
+
const { appsList: appsList2 } = await Promise.resolve().then(() => (init_apps(), exports_apps));
|
|
4638
|
+
await appsList2();
|
|
4639
|
+
});
|
|
4640
|
+
appsCmd.command("get <slug>").description("Get details for a specific app").action(async (slug) => {
|
|
4641
|
+
const { appsGet: appsGet2 } = await Promise.resolve().then(() => (init_apps(), exports_apps));
|
|
4642
|
+
await appsGet2(slug);
|
|
4643
|
+
});
|
|
4644
|
+
var logsCmd = program2.command("logs").description("View execution logs for deployed apps");
|
|
4645
|
+
logsCmd.command("list").description("List recent log entries").option("--app <slug>", "App slug (defaults to bagdock.json slug)").option("--limit <n>", "Number of entries", "50").action(async (opts) => {
|
|
4646
|
+
const { logsList: logsList2 } = await Promise.resolve().then(() => (init_logs(), exports_logs));
|
|
4647
|
+
await logsList2(opts);
|
|
4648
|
+
});
|
|
4649
|
+
logsCmd.command("get <id>").description("Get a specific log entry").option("--app <slug>", "App slug (defaults to bagdock.json slug)").action(async (id, opts) => {
|
|
4650
|
+
const { logsGet: logsGet2 } = await Promise.resolve().then(() => (init_logs(), exports_logs));
|
|
4651
|
+
await logsGet2(id, opts);
|
|
4652
|
+
});
|
|
4653
|
+
logsCmd.command("tail").description("Stream logs in real-time").option("--app <slug>", "App slug (defaults to bagdock.json slug)").action(async (opts) => {
|
|
4654
|
+
const { logsTail: logsTail2 } = await Promise.resolve().then(() => (init_logs(), exports_logs));
|
|
4655
|
+
await logsTail2(opts);
|
|
4656
|
+
});
|
|
3948
4657
|
program2.parse();
|