@tokenbuddy/tb-admin 1.0.37 → 1.0.39

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/dist/src/cli.js CHANGED
@@ -203,7 +203,7 @@ export function buildAdminCli(configManager) {
203
203
  .option("--token <token>", "Operator Bearer token")
204
204
  .option("--profile <profile>", "Use custom profile instead of default")
205
205
  .option("--config <path>", "Use custom config file path")
206
- .option("--workdir <path>", "Admin workdir path (default: $TB_ADMIN_WORKDIR or ~/.config/tokenbuddy)");
206
+ .option("--workdir <path>", "Admin workdir path (default: $TB_ADMIN_WORKDIR or ~/.config/tb-admin)");
207
207
  bindAdminUiCommand(program, configManager);
208
208
  function getRootConfigManager() {
209
209
  const opts = program.opts();
@@ -216,7 +216,7 @@ export function buildAdminCli(configManager) {
216
216
  .command("init")
217
217
  .description("Initialize an admin workdir for provider-specific deployment assets")
218
218
  .option("--provider <provider>", "Deployment provider (default: fly.io)", "fly.io")
219
- .option("--workdir <path>", "Admin workdir path (default: root --workdir, $TB_ADMIN_WORKDIR, or ~/.config/tokenbuddy)")
219
+ .option("--workdir <path>", "Admin workdir path (default: root --workdir, $TB_ADMIN_WORKDIR, or ~/.config/tb-admin)")
220
220
  .option("--check-only", "Only check provider requirements; do not write files")
221
221
  .option("--force", "Refresh regenerable templates without overwriting runtime secret files")
222
222
  .option("--install-tools", "Install missing provider CLI tools when supported")
@@ -1158,13 +1158,13 @@ export function buildAdminCli(configManager) {
1158
1158
  }
1159
1159
  });
1160
1160
  // Step 14 (v1.1): 多 vendor 实例隔离.
1161
- // 默认 config dir 改成 ~/.config/tokenbuddy/profiles/*.toml, 每个 vendor 一份 config.
1161
+ // 默认 config dir 改成 ~/.config/tb-admin/profiles/*.toml, 每个 vendor 一份 config.
1162
1162
  // 启动时 tb-admin (没传 --config) 会扫描 profiles/ 合并成一个虚拟配置 (default_profile 仍来自
1163
- // ~/.config/tokenbuddy/admin.toml). `tb-admin config ls` 列出当前 active file,
1163
+ // ~/.config/tb-admin/admin.toml). `tb-admin config ls` 列出当前 active file,
1164
1164
  // `tb-admin config profiles` 扫描 profiles/ 列出所有 vendor file.
1165
1165
  configCmd
1166
1166
  .command("profiles")
1167
- .description("Scan the vendor profiles directory (~/.config/tokenbuddy/profiles/) and list every vendor config")
1167
+ .description("Scan the vendor profiles directory (~/.config/tb-admin/profiles/) and list every vendor config")
1168
1168
  .action(() => {
1169
1169
  const profileDir = defaultProfileDir();
1170
1170
  const files = listProfileFiles(profileDir);
@@ -1530,8 +1530,8 @@ function collectIds(value, previous) {
1530
1530
  return previous.concat([value]);
1531
1531
  }
1532
1532
  // Step 14 (v1.1): 多 vendor 实例 config 隔离.
1533
- // 默认 profiles 目录是 ~/.config/tokenbuddy/profiles/, 每个 vendor 一份独立 toml.
1534
- // 默认主 config 仍走 ~/.config/tokenbuddy/admin.toml (default_profile 在此设).
1533
+ // 默认 profiles 目录是 ~/.config/tb-admin/profiles/, 每个 vendor 一份独立 toml.
1534
+ // 默认主 config 仍走 ~/.config/tb-admin/admin.toml (default_profile 在此设).
1535
1535
  // 用户可以:
1536
1536
  // - tb-admin --config /path/to/vendor-A.toml config ls (单 vendor 显式)
1537
1537
  // - tb-admin config profiles (扫 profiles/ 看所有 vendor)
@@ -1541,7 +1541,7 @@ function defaultProfileDir() {
1541
1541
  if (override) {
1542
1542
  return path.join(override, "profiles");
1543
1543
  }
1544
- return path.join(process.env.HOME || "", ".config", "tokenbuddy", "profiles");
1544
+ return path.join(process.env.HOME || "", ".config", "tb-admin", "profiles");
1545
1545
  }
1546
1546
  function listProfileFiles(dir) {
1547
1547
  if (!fs.existsSync(dir)) {
@@ -50,7 +50,7 @@ export interface AdminConfig {
50
50
  };
51
51
  }
52
52
  /**
53
- * 解析 admin CLI 的默认配置路径:`~/.config/tokenbuddy/admin.toml`。
53
+ * 解析 admin CLI 的默认配置路径:`~/.config/tb-admin/admin.toml`。
54
54
  * 兼容旧版 `~/.tokenbuddy/admin.json`(legacy JSON),由 `ConfigManager` 自动识别。
55
55
  *
56
56
  * @returns 配置文件绝对路径
@@ -4,7 +4,7 @@ import * as os from "os";
4
4
  import TOML from "@iarna/toml";
5
5
  import { defaultAdminConfigPath, defaultAdminWorkdir, resolveAdminConfigPath, resolveAdminWorkdir } from "./workdir.js";
6
6
  /**
7
- * 解析 admin CLI 的默认配置路径:`~/.config/tokenbuddy/admin.toml`。
7
+ * 解析 admin CLI 的默认配置路径:`~/.config/tb-admin/admin.toml`。
8
8
  * 兼容旧版 `~/.tokenbuddy/admin.json`(legacy JSON),由 `ConfigManager` 自动识别。
9
9
  *
10
10
  * @returns 配置文件绝对路径
@@ -623,7 +623,7 @@ function renderDetail(){
623
623
  const d = currentDetail;
624
624
  document.getElementById("detailTitle").textContent = d.row.name + " detail";
625
625
  document.getElementById("editDetail").textContent = editing ? "Save changes" : "Edit config";
626
- document.getElementById("deleteSeller").title = deleteReady ? "Confirm destroy deployment" : "Delete deployment";
626
+ document.getElementById("deleteSeller").title = "Delete deployment";
627
627
  showDetailStatus(d.row.error || "", false);
628
628
  document.getElementById("detailGrid").classList.remove("hidden");
629
629
  const c = d.configuration;
@@ -647,7 +647,7 @@ function setStatusActionBusy(busy){ document.querySelectorAll("[data-status-acti
647
647
  function setDetailSavingBusy(busy){ const edit = document.getElementById("editDetail"); edit.disabled = Boolean(busy); edit.textContent = busy ? "Saving" : (editing ? "Save changes" : "Edit config"); document.querySelectorAll("#detailGrid [data-field], #detailGrid [data-model], #detailGrid [data-model-enabled], [data-status-action], #deleteSeller").forEach(input => { input.disabled = Boolean(busy); }); }
648
648
  document.getElementById("editDetail").onclick = async () => { if (!editing){ editing = true; renderDetail(); return; } const patch = {}; document.querySelectorAll("[data-field]").forEach(input => { const value = input.value; if (value === "" || value === input.dataset.original) return; patch[input.dataset.field] = numeric(value); }); const aliases = {}; document.querySelectorAll("[data-model]").forEach(input => aliases[input.dataset.model] = input.value); patch.modelAliases = aliases; patch.models = modelConfigPatchFromDetail(); try { setDetailSavingBusy(true); showDetailStatus("Saving seller config", true); const result = await api("/api/sellers/"+encodeURIComponent(currentDetail.row.id)+"/config", { method:"PUT", body: JSON.stringify(patch) }); if (!result.ok) throw new Error(result.stderr || "Save failed"); currentDetail = await api("/api/sellers/"+encodeURIComponent(currentDetail.row.id)); editing = false; renderDetail(); loadSellers(); } catch (err) { showDetailStatus(err.message || "Save failed", false); } finally { setDetailSavingBusy(false); } };
649
649
  function modelConfigPatchFromDetail(){ const enabledByModel = {}; document.querySelectorAll("[data-model-enabled]").forEach(input => enabledByModel[input.dataset.modelEnabled] = Boolean(input.checked)); return (currentDetail?.models || []).map(model => ({ ...(model.configModel || { id:model.upstreamModel }), id:model.upstreamModel, enabled: enabledByModel[model.upstreamModel] !== false })); }
650
- document.getElementById("deleteSeller").onclick = async () => { if (!currentDetail) return; if (deleteReady && !confirm("Destroy deployment for "+currentDetail.row.name+"?")) return; const result = await api("/api/sellers/"+encodeURIComponent(currentDetail.row.id)+"/deployment", { method:"DELETE", body: JSON.stringify({ confirm: deleteReady }) }); showDetailStatus(result.stdout || (deleteReady ? "Deployment destroy requested." : "Dry-run ready. Click delete again to confirm destroy."), false); deleteReady = !deleteReady; document.getElementById("deleteSeller").title = deleteReady ? "Confirm destroy deployment" : "Delete deployment"; };
650
+ document.getElementById("deleteSeller").onclick = async () => { if (!currentDetail) return; if (!confirm("Destroy deployment for "+currentDetail.row.name+"?")) return; try { setDetailSavingBusy(true); showDetailStatus("Destroying deployment", true); const result = await api("/api/sellers/"+encodeURIComponent(currentDetail.row.id)+"/deployment", { method:"DELETE", body: JSON.stringify({ confirm: true }) }); if (!result.ok) throw new Error(result.stderr || "Deployment destroy failed."); showDetailStatus(result.stdout || "Deployment destroy requested.", false); deleteReady = false; document.getElementById("deleteSeller").title = "Delete deployment"; loadSellers(); } catch (err) { showDetailStatus(err.message || "Deployment destroy failed.", false); } finally { setDetailSavingBusy(false); } };
651
651
  document.getElementById("closeDetail").onclick = () => { deleteReady = false; document.getElementById("detailModal").classList.remove("open"); };
652
652
  document.getElementById("hideNoInstanceApps").onchange = event => { hideNoInstanceApps = Boolean(event.target.checked); renderSellerRows(sellerRowsCache); };
653
653
  document.querySelectorAll("[data-status-action]").forEach(btn => btn.onclick = async () => { if (!currentDetail) return; const action = btn.dataset.statusAction; const id = currentDetail.row.id; const status = registryStatusForAction(action); try { setStatusActionBusy(true); showDetailStatus("Updating registry status", true); const result = await api("/api/sellers/"+encodeURIComponent(id)+"/"+action, { method:"POST" }); if (!result.ok) throw new Error(result.stderr || "Status update failed."); patchSellerRegistryStatus(id, status); deleteReady = false; currentDetail = null; document.getElementById("detailModal").classList.remove("open"); } catch (err) { showDetailStatus(err.message || "Status update failed.", false); } finally { setStatusActionBusy(false); } });
@@ -2,7 +2,7 @@ import * as os from "os";
2
2
  import * as path from "path";
3
3
  export const TB_ADMIN_WORKDIR_ENV = "TB_ADMIN_WORKDIR";
4
4
  export const TOKENBUDDY_ADMIN_CONFIG_ENV = "TOKENBUDDY_ADMIN_CONFIG";
5
- export const DEFAULT_ADMIN_WORKDIR_RELATIVE = path.join(".config", "tokenbuddy");
5
+ export const DEFAULT_ADMIN_WORKDIR_RELATIVE = path.join(".config", "tb-admin");
6
6
  function expandHome(input, homeDir) {
7
7
  if (input === "~") {
8
8
  return homeDir;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@tokenbuddy/tb-admin",
3
- "version": "1.0.37",
3
+ "version": "1.0.39",
4
4
  "description": "Remote admin CLI for TokenBuddy seller apps",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
7
7
  "type": "module",
8
8
  "bin": {
9
- "tb-admin": "./bin/tb-admin.js"
9
+ "tb-admin": "bin/tb-admin.js"
10
10
  },
11
11
  "private": false,
12
12
  "files": [
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@iarna/toml": "^2.2.5",
23
- "@tokenbuddy/contracts": "^1.0.37",
23
+ "@tokenbuddy/contracts": "^1.0.39",
24
24
  "@types/js-yaml": "^4.0.9",
25
25
  "cli-table3": "^0.6.4",
26
26
  "commander": "^12.0.0",