@pmate/cli 0.28.2 → 0.28.4

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.
Files changed (2) hide show
  1. package/dist/index.js +69 -25
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12554,6 +12554,7 @@ var DevCommandHandler = class {
12554
12554
  // src/commands/OssCommandHandler.ts
12555
12555
  var import_node_fs6 = require("fs");
12556
12556
  var import_node_path10 = __toESM(require("path"));
12557
+ var PARROT_STATIC_PUBLIC_BASE_URL = "https://parrot-static.pmate.chat";
12557
12558
  var OssCommandHandler = class _OssCommandHandler {
12558
12559
  static {
12559
12560
  this.DEFAULT_BUCKET = "parrot-static";
@@ -12575,6 +12576,10 @@ var OssCommandHandler = class _OssCommandHandler {
12575
12576
  const objectKey = this.normalizeObjectKey(args.objectKey);
12576
12577
  const bucket = this.resolveBucket(args.bucket);
12577
12578
  await AliyunService.uploadFile(resolvedFile, bucket, objectKey);
12579
+ const publicUrl = buildOssPublicUrl(bucket, objectKey);
12580
+ if (publicUrl) {
12581
+ ui.plain(publicUrl);
12582
+ }
12578
12583
  }
12579
12584
  assertFile(filePath) {
12580
12585
  if (!(0, import_node_fs6.existsSync)(filePath)) {
@@ -12600,6 +12605,11 @@ var OssCommandHandler = class _OssCommandHandler {
12600
12605
  return _OssCommandHandler.DEFAULT_BUCKET;
12601
12606
  }
12602
12607
  };
12608
+ function buildOssPublicUrl(bucket, objectKey) {
12609
+ if (bucket !== "parrot-static") return null;
12610
+ const encodedKey = objectKey.split("/").map((segment) => encodeURIComponent(segment)).join("/");
12611
+ return `${PARROT_STATIC_PUBLIC_BASE_URL}/${encodedKey}`;
12612
+ }
12603
12613
 
12604
12614
  // src/commands/EnvCommandHandler.ts
12605
12615
  var import_node_path11 = __toESM(require("path"));
@@ -24420,33 +24430,70 @@ var HostCommandHandler = class {
24420
24430
  return;
24421
24431
  }
24422
24432
  const resolved = await client.resolveHostEnv(hostId);
24423
- const result = applyHostEnv(resolved.values);
24433
+ const result = await applyHostEnvRemote(hostId, resolved.values);
24424
24434
  if (args.json) ui.plain(JSON.stringify({ hostId, ...result }, null, 2));
24425
24435
  else ui.success(`Applied ${Object.keys(resolved.values).length} host env vars`, result.envFile);
24426
24436
  }
24427
24437
  };
24428
- function applyHostEnv(values, home = (0, import_node_os11.homedir)()) {
24429
- const hostDir = import_node_path30.default.join(home, ".pmate", "host");
24430
- const envFile = import_node_path30.default.join(hostDir, "host.env");
24431
- const tempFile = import_node_path30.default.join(hostDir, `.host.env.${process.pid}.tmp`);
24432
- const profileFile = import_node_path30.default.join(home, ".profile");
24433
- (0, import_node_fs25.mkdirSync)(hostDir, { recursive: true });
24434
- const content = Object.entries(values).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${normalizeEnvKey(key)}=${shellQuote3(value)}`).join("\n") + "\n";
24435
- (0, import_node_fs25.writeFileSync)(tempFile, content, { mode: 384 });
24436
- (0, import_node_fs25.chmodSync)(tempFile, 384);
24437
- (0, import_node_fs25.renameSync)(tempFile, envFile);
24438
- (0, import_node_fs25.chmodSync)(envFile, 384);
24439
- const existing = (0, import_node_fs25.existsSync)(profileFile) ? (0, import_node_fs25.readFileSync)(profileFile, "utf8") : "";
24440
- const blockPattern = new RegExp(`${escapeRegExp(BLOCK_START)}[\\s\\S]*?${escapeRegExp(BLOCK_END)}\\n?`, "g");
24441
- const withoutBlock = existing.replace(blockPattern, "").trimEnd();
24442
- const profileContent = `${withoutBlock}${withoutBlock ? "\n\n" : ""}${PROFILE_BLOCK}
24438
+ async function applyHostEnvRemote(host, values) {
24439
+ const target = `pmate@${normalizeHostId(host)}`;
24440
+ const content = serializeHostEnv(values);
24441
+ const script = buildRemoteApplyScript(Buffer.from(content, "utf8").toString("base64"));
24442
+ await new Promise((resolve, reject) => {
24443
+ const child = (0, import_node_child_process13.spawn)("ssh", [target, "bash -s"], { stdio: ["pipe", "pipe", "pipe"] });
24444
+ let stdout = "";
24445
+ let stderr = "";
24446
+ child.stdout.on("data", (chunk) => {
24447
+ stdout += chunk.toString();
24448
+ });
24449
+ child.stderr.on("data", (chunk) => {
24450
+ stderr += chunk.toString();
24451
+ });
24452
+ child.on("error", reject);
24453
+ child.on("close", (code) => {
24454
+ if (code === 0) resolve();
24455
+ else reject(new Error(`ssh to ${host} failed${stderr.trim() ? `: ${stderr.trim()}` : ` with code ${code}`}
24456
+ ${stdout.trim()}`.trim()));
24457
+ });
24458
+ child.stdin.end(script);
24459
+ });
24460
+ return {
24461
+ envFile: "~/.pmate/host/host.env",
24462
+ profileFile: "~/.profile",
24463
+ refreshed: true
24464
+ };
24465
+ }
24466
+ function buildRemoteApplyScript(contentBase64) {
24467
+ return `set -euo pipefail
24468
+ host_dir="$HOME/.pmate/host"
24469
+ env_file="$host_dir/host.env"
24470
+ profile_file="$HOME/.profile"
24471
+ mkdir -p "$host_dir"
24472
+ env_tmp="$(mktemp "$host_dir/.host.env.XXXXXX")"
24473
+ profile_tmp=""
24474
+ cleanup() { rm -f "$env_tmp"; [ -z "$profile_tmp" ] || rm -f "$profile_tmp"; }
24475
+ trap cleanup EXIT
24476
+ printf '%s' '${contentBase64}' | base64 --decode > "$env_tmp"
24477
+ chmod 600 "$env_tmp"
24478
+ mv "$env_tmp" "$env_file"
24479
+ touch "$profile_file"
24480
+ profile_tmp="$(mktemp "$HOME/.profile.XXXXXX")"
24481
+ awk '
24482
+ $0 == "${BLOCK_START}" { managed = 1; next }
24483
+ $0 == "${BLOCK_END}" { managed = 0; next }
24484
+ !managed { print }
24485
+ ' "$profile_file" > "$profile_tmp"
24486
+ while [ -s "$profile_tmp" ] && [ "$(tail -c 1 "$profile_tmp" | wc -l)" -eq 0 ]; do printf '\\n' >> "$profile_tmp"; done
24487
+ cat >> "$profile_tmp" <<'PMATE_PROFILE_BLOCK'
24488
+ ${PROFILE_BLOCK}
24489
+ PMATE_PROFILE_BLOCK
24490
+ mv "$profile_tmp" "$profile_file"
24491
+ bash -lc '. "$HOME/.profile"'
24492
+ printf 'applied %s\\n' "$env_file"
24443
24493
  `;
24444
- const profileTemp = `${profileFile}.${process.pid}.tmp`;
24445
- (0, import_node_fs25.writeFileSync)(profileTemp, profileContent);
24446
- (0, import_node_fs25.renameSync)(profileTemp, profileFile);
24447
- const check = (0, import_node_child_process13.spawnSync)("bash", ["-lc", `. ${shellQuote3(profileFile)}`], { cwd: home, env: { ...process.env, HOME: home }, encoding: "utf8" });
24448
- if (check.status !== 0) throw new Error(`Host env refresh validation failed: ${check.stderr.trim()}`);
24449
- return { envFile, profileFile, refreshed: true };
24494
+ }
24495
+ function serializeHostEnv(values) {
24496
+ return Object.entries(values).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${normalizeEnvKey(key)}=${shellQuote3(value)}`).join("\n") + "\n";
24450
24497
  }
24451
24498
  function normalizeHostId(value) {
24452
24499
  const normalized = value.trim();
@@ -24460,9 +24507,6 @@ function normalizeEnvKey(value) {
24460
24507
  function shellQuote3(value) {
24461
24508
  return `'${value.replace(/'/g, `'"'"'`)}'`;
24462
24509
  }
24463
- function escapeRegExp(value) {
24464
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
24465
- }
24466
24510
  function requireArg(value, name) {
24467
24511
  if (value === void 0) throw new Error(`Missing ${name}`);
24468
24512
  return value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmate/cli",
3
- "version": "0.28.2",
3
+ "version": "0.28.4",
4
4
  "description": "CLI utilities for the pMate project",
5
5
  "license": "MIT",
6
6
  "bin": {