@tinycloud/cli 1.5.0-beta.11 → 1.5.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -0
- package/dist/index.js.map +1 -1
- package/dist/legacy-entry.js +294 -61
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +5 -5
- package/skills/tc-cli/REFERENCE.md +22 -1
package/dist/legacy-entry.js
CHANGED
|
@@ -5259,6 +5259,9 @@ function assertReadable(authority, now) {
|
|
|
5259
5259
|
function contentHash(bytes) {
|
|
5260
5260
|
return bytesToHex(blake3(bytes));
|
|
5261
5261
|
}
|
|
5262
|
+
function repairId(entry) {
|
|
5263
|
+
return `${entry.hash}\0${entry.key}`;
|
|
5264
|
+
}
|
|
5262
5265
|
function sameEtag(a, b) {
|
|
5263
5266
|
return a.replace(/^"|"$/g, "") === b.replace(/^"|"$/g, "");
|
|
5264
5267
|
}
|
|
@@ -5628,7 +5631,7 @@ function kvSyncTransport(kv, options = {}) {
|
|
|
5628
5631
|
}
|
|
5629
5632
|
};
|
|
5630
5633
|
}
|
|
5631
|
-
var ReplicaErrorCode, REPLICA_ERROR, ReplicaError, RFC3339, DEFAULT_PAGE_LIMIT, DEFAULT_LEASE_TTL_MS, FETCH_CHUNK, REPAIR_BATCH, RETENTION_REVOKED, PENDING_REFUSALS, Replica, BASE58, BASE32, featureCache, REVOKED_CODES, REVOKED_BODY, encoder;
|
|
5634
|
+
var ReplicaErrorCode, REPLICA_ERROR, ReplicaError, RFC3339, DEFAULT_PAGE_LIMIT, DEFAULT_LEASE_TTL_MS, FETCH_CHUNK, REPAIR_BATCH, REPAIR_MAX_TRIES, REPAIR_BACKOFF_BASE_MS, RETENTION_REVOKED, PENDING_REFUSALS, Replica, BASE58, BASE32, featureCache, REVOKED_CODES, REVOKED_BODY, encoder;
|
|
5632
5635
|
var init_dist = __esm({
|
|
5633
5636
|
"../replica/dist/index.js"() {
|
|
5634
5637
|
"use strict";
|
|
@@ -5716,6 +5719,8 @@ var init_dist = __esm({
|
|
|
5716
5719
|
DEFAULT_LEASE_TTL_MS = 12e4;
|
|
5717
5720
|
FETCH_CHUNK = 100;
|
|
5718
5721
|
REPAIR_BATCH = 100;
|
|
5722
|
+
REPAIR_MAX_TRIES = 5;
|
|
5723
|
+
REPAIR_BACKOFF_BASE_MS = 6e4;
|
|
5719
5724
|
RETENTION_REVOKED = /* @__PURE__ */ new Set(["retention-grant-revoked", "retention-grant-ancestor-revoked"]);
|
|
5720
5725
|
PENDING_REFUSALS = /* @__PURE__ */ new Set([
|
|
5721
5726
|
ReplicaErrorCode.GRANT_UNAUTHORIZED,
|
|
@@ -5728,6 +5733,8 @@ var init_dist = __esm({
|
|
|
5728
5733
|
#now;
|
|
5729
5734
|
#leaseTtlMs;
|
|
5730
5735
|
#onCommit;
|
|
5736
|
+
/** Failed repair fetches of this session, by key and ETag hash. Never persisted: a new `Replica` retries afresh. */
|
|
5737
|
+
#repairTries = /* @__PURE__ */ new Map();
|
|
5731
5738
|
constructor(options) {
|
|
5732
5739
|
this.#store = options.store;
|
|
5733
5740
|
const transport = options.transport;
|
|
@@ -6082,7 +6089,14 @@ var init_dist = __esm({
|
|
|
6082
6089
|
return { changes, blobs, fetched: fetched2 };
|
|
6083
6090
|
}
|
|
6084
6091
|
async #repair(attempt, cursor, nodeDid, coverage, retentionGrantCid) {
|
|
6085
|
-
const
|
|
6092
|
+
const all = await this.#store.pendingRepairs(Number.MAX_SAFE_INTEGER);
|
|
6093
|
+
const now = this.#now();
|
|
6094
|
+
const pendingIds = new Set(all.map((entry) => repairId(entry)));
|
|
6095
|
+
for (const id of this.#repairTries.keys()) if (!pendingIds.has(id)) this.#repairTries.delete(id);
|
|
6096
|
+
const pending = all.filter((entry) => {
|
|
6097
|
+
const state2 = this.#repairTries.get(repairId(entry));
|
|
6098
|
+
return state2 === void 0 || state2.tries < REPAIR_MAX_TRIES && now >= state2.nextAttemptAt;
|
|
6099
|
+
});
|
|
6086
6100
|
let repaired = 0;
|
|
6087
6101
|
for (let start = 0; start < pending.length; start += REPAIR_BATCH) {
|
|
6088
6102
|
const chunk = pending.slice(start, start + REPAIR_BATCH);
|
|
@@ -6094,7 +6108,14 @@ var init_dist = __esm({
|
|
|
6094
6108
|
const changes = [];
|
|
6095
6109
|
for (const entry of chunk) {
|
|
6096
6110
|
const bytes = acceptContent(entry, contents.get(entry.key));
|
|
6097
|
-
|
|
6111
|
+
const id = repairId(entry);
|
|
6112
|
+
if (bytes === void 0) {
|
|
6113
|
+
const tries = (this.#repairTries.get(id)?.tries ?? 0) + 1;
|
|
6114
|
+
const wait = tries === 1 ? 0 : REPAIR_BACKOFF_BASE_MS * 2 ** (tries - 2);
|
|
6115
|
+
this.#repairTries.set(id, { tries, nextAttemptAt: this.#now() + wait });
|
|
6116
|
+
continue;
|
|
6117
|
+
}
|
|
6118
|
+
this.#repairTries.delete(id);
|
|
6098
6119
|
blobs.set(entry.hash, bytes);
|
|
6099
6120
|
changes.push({ ...entry, content: true });
|
|
6100
6121
|
}
|
|
@@ -39167,7 +39188,7 @@ init_constants();
|
|
|
39167
39188
|
import { CLI_NAME as CLI_NAME32 } from "@tinycloud/operations/cli-name";
|
|
39168
39189
|
import { readFile as readFile14 } from "fs/promises";
|
|
39169
39190
|
import { join as join17 } from "path";
|
|
39170
|
-
import { homedir, hostname, userInfo } from "os";
|
|
39191
|
+
import { constants as osConstants, homedir, hostname, userInfo } from "os";
|
|
39171
39192
|
import { appSecretScope } from "@tinycloud/sdk-core";
|
|
39172
39193
|
import { invokeOperation as invokeOperation3 } from "@tinycloud/operations";
|
|
39173
39194
|
import { isLocalOwnerProfile as isLocalOwnerProfile4, ownerSessionLacksProof as ownerSessionLacksProof5 } from "@tinycloud/operations/profile";
|
|
@@ -39188,6 +39209,7 @@ import {
|
|
|
39188
39209
|
} from "@tinycloud/operations/secret-capabilities";
|
|
39189
39210
|
import { invokeSecretsGetWithLocalAuthorityRetry } from "@tinycloud/operations/cli-runtime";
|
|
39190
39211
|
init_sdk();
|
|
39212
|
+
init_replication_registry();
|
|
39191
39213
|
init_session_expired();
|
|
39192
39214
|
init_space();
|
|
39193
39215
|
|
|
@@ -39253,14 +39275,14 @@ function runProbeChild(request, options = {}) {
|
|
|
39253
39275
|
const args = options.argv ?? probeChildArgv(request);
|
|
39254
39276
|
const budgetMs = options.budgetMs ?? ATTEMPT_BUDGET_MS;
|
|
39255
39277
|
const killGraceMs = options.killGraceMs ?? KILL_GRACE_MS;
|
|
39256
|
-
const
|
|
39278
|
+
const spawn3 = options.spawn ?? nodeSpawn;
|
|
39257
39279
|
const signal = options.signal;
|
|
39258
39280
|
return new Promise((resolve9) => {
|
|
39259
39281
|
if (signal?.aborted) {
|
|
39260
39282
|
resolve9({ kind: "cancelled" });
|
|
39261
39283
|
return;
|
|
39262
39284
|
}
|
|
39263
|
-
const child =
|
|
39285
|
+
const child = spawn3(command, args, { env: process.env, stdio: ["ignore", "pipe", "pipe"] });
|
|
39264
39286
|
let outcome;
|
|
39265
39287
|
let stdout = Buffer.alloc(0);
|
|
39266
39288
|
let stderr = Buffer.alloc(0);
|
|
@@ -39372,6 +39394,75 @@ function parseStatusEnvelope(line) {
|
|
|
39372
39394
|
return void 0;
|
|
39373
39395
|
}
|
|
39374
39396
|
|
|
39397
|
+
// src/lib/run-command.ts
|
|
39398
|
+
import { execFileSync, spawn as spawn2 } from "child_process";
|
|
39399
|
+
import { existsSync, readFileSync as readFileSync2 } from "fs";
|
|
39400
|
+
var FORWARDED_SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP", "SIGQUIT"];
|
|
39401
|
+
var TERMINAL_SIGNALS = { SIGINT: true, SIGQUIT: true, SIGHUP: true };
|
|
39402
|
+
function psGroupArgs(pid) {
|
|
39403
|
+
return ["-o", "pgid=", "-o", "tpgid=", "-p", String(pid)];
|
|
39404
|
+
}
|
|
39405
|
+
function parsePsGroups(output2) {
|
|
39406
|
+
const columns = output2.trim().split(/\s+/);
|
|
39407
|
+
if (columns.length !== 2) return void 0;
|
|
39408
|
+
const group = Number(columns[0]);
|
|
39409
|
+
const foreground = Number(columns[1]);
|
|
39410
|
+
return Number.isSafeInteger(group) && Number.isSafeInteger(foreground) ? { group, foreground } : void 0;
|
|
39411
|
+
}
|
|
39412
|
+
function processGroups() {
|
|
39413
|
+
try {
|
|
39414
|
+
const stat8 = readFileSync2("/proc/self/stat", "utf8");
|
|
39415
|
+
const fields = stat8.slice(stat8.lastIndexOf(")") + 2).split(" ");
|
|
39416
|
+
return { group: Number(fields[2]), foreground: Number(fields[5]) };
|
|
39417
|
+
} catch {
|
|
39418
|
+
}
|
|
39419
|
+
try {
|
|
39420
|
+
const ps = existsSync("/bin/ps") ? "/bin/ps" : "/usr/bin/ps";
|
|
39421
|
+
return parsePsGroups(execFileSync(ps, psGroupArgs(process.pid), {
|
|
39422
|
+
env: {},
|
|
39423
|
+
encoding: "utf8",
|
|
39424
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
39425
|
+
timeout: 2e3
|
|
39426
|
+
}));
|
|
39427
|
+
} catch {
|
|
39428
|
+
return void 0;
|
|
39429
|
+
}
|
|
39430
|
+
}
|
|
39431
|
+
function inTerminalForeground() {
|
|
39432
|
+
const groups = processGroups();
|
|
39433
|
+
return groups !== void 0 && groups.foreground > 0 && groups.group === groups.foreground;
|
|
39434
|
+
}
|
|
39435
|
+
function runCommand(argv, env) {
|
|
39436
|
+
return new Promise((resolve9) => {
|
|
39437
|
+
let child;
|
|
39438
|
+
try {
|
|
39439
|
+
child = spawn2(argv[0], argv.slice(1), { stdio: "inherit", env, shell: false });
|
|
39440
|
+
} catch (error) {
|
|
39441
|
+
const code5 = error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
39442
|
+
resolve9({ kind: "not_started", ...code5 === void 0 ? {} : { errno: code5 } });
|
|
39443
|
+
return;
|
|
39444
|
+
}
|
|
39445
|
+
const forward = (signal) => {
|
|
39446
|
+
if (TERMINAL_SIGNALS[signal] && inTerminalForeground()) return;
|
|
39447
|
+
child.kill(signal);
|
|
39448
|
+
};
|
|
39449
|
+
for (const signal of FORWARDED_SIGNALS) process.on(signal, forward);
|
|
39450
|
+
const settle = (outcome) => {
|
|
39451
|
+
for (const signal of FORWARDED_SIGNALS) process.off(signal, forward);
|
|
39452
|
+
resolve9(outcome);
|
|
39453
|
+
};
|
|
39454
|
+
child.on("error", (error) => {
|
|
39455
|
+
if (child.pid === void 0) settle({ kind: "not_started", ...error.code === void 0 ? {} : { errno: error.code } });
|
|
39456
|
+
});
|
|
39457
|
+
child.once("exit", (code5, signal) => {
|
|
39458
|
+
settle(signal !== null ? { kind: "signaled", signal } : { kind: "exited", code: code5 ?? 1 });
|
|
39459
|
+
});
|
|
39460
|
+
});
|
|
39461
|
+
}
|
|
39462
|
+
|
|
39463
|
+
// src/commands/secrets.ts
|
|
39464
|
+
init_safe_text();
|
|
39465
|
+
|
|
39375
39466
|
// src/lib/secrets-wait.ts
|
|
39376
39467
|
init_constants();
|
|
39377
39468
|
init_errors();
|
|
@@ -40326,6 +40417,153 @@ function outputSecretDoctor(result) {
|
|
|
40326
40417
|
process.stdout.write(theme.warn(`${failed} secrets check${failed > 1 ? "s" : ""} need attention.`) + "\n");
|
|
40327
40418
|
}
|
|
40328
40419
|
}
|
|
40420
|
+
async function resolveSecretReadTarget(ctx, name, options) {
|
|
40421
|
+
const scopeOptions = resolveSecretScope(options);
|
|
40422
|
+
const legacySpaceUri = await resolveSecretSpace(options.space, ctx.profile);
|
|
40423
|
+
const resolved = resolveSecretPath2(name, scopeOptions);
|
|
40424
|
+
return { name, scopeOptions, scope: resolved.scope, legacySpaceUri, secretPath: resolved.permissionPaths.vault };
|
|
40425
|
+
}
|
|
40426
|
+
async function readSecret(params) {
|
|
40427
|
+
const { ctx, target, options } = params;
|
|
40428
|
+
const { name } = target;
|
|
40429
|
+
if (options.delegation) {
|
|
40430
|
+
const delegated = await resolveDelegatedSecretSource(
|
|
40431
|
+
options.delegation,
|
|
40432
|
+
target.secretPath,
|
|
40433
|
+
target.legacySpaceUri ?? SECRETS_SPACE2
|
|
40434
|
+
);
|
|
40435
|
+
const effectiveHost = params.host ?? delegated.delegation.host ?? ctx.host;
|
|
40436
|
+
const delegatedCtx = { ...ctx, host: effectiveHost };
|
|
40437
|
+
const local = effectiveLocal(await ProfileManager.getProfile(ctx.profile).catch(() => null), options);
|
|
40438
|
+
const node = await ensureSecretsNode(delegatedCtx, options);
|
|
40439
|
+
const value = await withSpinner(
|
|
40440
|
+
`Getting secret ${name}...`,
|
|
40441
|
+
() => readDelegatedSecretValue({
|
|
40442
|
+
node,
|
|
40443
|
+
delegation: delegated.delegation,
|
|
40444
|
+
delegationCid: delegated.delegation.cid,
|
|
40445
|
+
permissions: delegated.permissions,
|
|
40446
|
+
secretPath: target.secretPath,
|
|
40447
|
+
space: target.legacySpaceUri ?? SECRETS_SPACE2,
|
|
40448
|
+
name,
|
|
40449
|
+
...target.scope === void 0 ? {} : { scope: target.scope },
|
|
40450
|
+
local
|
|
40451
|
+
})
|
|
40452
|
+
);
|
|
40453
|
+
return { value };
|
|
40454
|
+
}
|
|
40455
|
+
const privateKey = authOptions(options)?.privateKey;
|
|
40456
|
+
const spaceUri = privateKey !== void 0 && options.space !== void 0 && !options.space.startsWith("tinycloud:") ? options.space : target.legacySpaceUri;
|
|
40457
|
+
const result = await invokeCanonicalSecretGet({
|
|
40458
|
+
ctx,
|
|
40459
|
+
name,
|
|
40460
|
+
...target.scopeOptions?.scope === void 0 ? {} : { scope: target.scopeOptions.scope },
|
|
40461
|
+
...spaceUri === void 0 ? {} : { space: spaceUri },
|
|
40462
|
+
options,
|
|
40463
|
+
label: `Getting secret ${name}...`,
|
|
40464
|
+
openKeyAcquisition: params.openKeyAcquisition
|
|
40465
|
+
});
|
|
40466
|
+
if (result.status !== "ok") {
|
|
40467
|
+
try {
|
|
40468
|
+
throwCanonicalSecretGetError(result, name);
|
|
40469
|
+
} catch (error) {
|
|
40470
|
+
throw withOperationWarnings(error, result.warnings);
|
|
40471
|
+
}
|
|
40472
|
+
}
|
|
40473
|
+
return { value: result.output.value, warnings: result.warnings };
|
|
40474
|
+
}
|
|
40475
|
+
var ENV_VAR_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
40476
|
+
function argvAfterSeparator(cmd) {
|
|
40477
|
+
let root = cmd;
|
|
40478
|
+
while (root.parent) root = root.parent;
|
|
40479
|
+
const raw = "rawArgs" in root ? root.rawArgs : void 0;
|
|
40480
|
+
if (!Array.isArray(raw)) return void 0;
|
|
40481
|
+
const args = raw.map(String);
|
|
40482
|
+
const withValue = (flag) => root.options.some((option) => option.required && (option.long === flag || option.short === flag));
|
|
40483
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
40484
|
+
const arg = args[index];
|
|
40485
|
+
if (arg === "--") return args.slice(index + 1);
|
|
40486
|
+
if (arg.startsWith("--")) {
|
|
40487
|
+
if (withValue(arg)) index += 1;
|
|
40488
|
+
continue;
|
|
40489
|
+
}
|
|
40490
|
+
if (arg.length < 2 || !arg.startsWith("-")) continue;
|
|
40491
|
+
for (let char = 1; char < arg.length; char += 1) {
|
|
40492
|
+
const option = root.options.find((candidate) => candidate.short === `-${arg[char]}`);
|
|
40493
|
+
if (option === void 0) break;
|
|
40494
|
+
if (option.required) {
|
|
40495
|
+
if (char === arg.length - 1) index += 1;
|
|
40496
|
+
break;
|
|
40497
|
+
}
|
|
40498
|
+
}
|
|
40499
|
+
}
|
|
40500
|
+
return void 0;
|
|
40501
|
+
}
|
|
40502
|
+
function secretRunPlan(cmd, operands, maps) {
|
|
40503
|
+
const usage3 = `${CLI_NAME32} secrets run NAME... [--map NAME=ENV_VAR] -- <command> [args...]`;
|
|
40504
|
+
const after = argvAfterSeparator(cmd);
|
|
40505
|
+
if (after === void 0 || after.length > operands.length) {
|
|
40506
|
+
throw new CLIError("USAGE_ERROR", `Put the command after \`--\`: ${usage3}`, ExitCode.USAGE_ERROR);
|
|
40507
|
+
}
|
|
40508
|
+
const [program, ...args] = after;
|
|
40509
|
+
if (program === void 0) {
|
|
40510
|
+
throw new CLIError("USAGE_ERROR", `Add the command to run after \`--\`: ${usage3}`, ExitCode.USAGE_ERROR);
|
|
40511
|
+
}
|
|
40512
|
+
const exports = [];
|
|
40513
|
+
for (const name of operands.slice(0, operands.length - after.length)) {
|
|
40514
|
+
if (!ENV_VAR_RE.test(name)) {
|
|
40515
|
+
throw new CLIError(
|
|
40516
|
+
"USAGE_ERROR",
|
|
40517
|
+
`${JSON.stringify(name)} can't be used as an environment variable name. Use \`--map ${name}=ENV_VAR\` to choose one.`,
|
|
40518
|
+
ExitCode.USAGE_ERROR
|
|
40519
|
+
);
|
|
40520
|
+
}
|
|
40521
|
+
exports.push({ name, variable: name });
|
|
40522
|
+
}
|
|
40523
|
+
for (const map of maps) {
|
|
40524
|
+
const equals7 = map.indexOf("=");
|
|
40525
|
+
const variable = map.slice(equals7 + 1);
|
|
40526
|
+
if (equals7 <= 0 || !ENV_VAR_RE.test(variable)) {
|
|
40527
|
+
throw new CLIError(
|
|
40528
|
+
"USAGE_ERROR",
|
|
40529
|
+
`Invalid \`--map ${JSON.stringify(map)}\`: use NAME=ENV_VAR, where ENV_VAR starts with a letter or _ and uses only letters, digits and _.`,
|
|
40530
|
+
ExitCode.USAGE_ERROR
|
|
40531
|
+
);
|
|
40532
|
+
}
|
|
40533
|
+
exports.push({ name: map.slice(0, equals7), variable });
|
|
40534
|
+
}
|
|
40535
|
+
if (exports.length === 0) {
|
|
40536
|
+
throw new CLIError("USAGE_ERROR", `Name at least one secret: ${usage3}`, ExitCode.USAGE_ERROR);
|
|
40537
|
+
}
|
|
40538
|
+
const variables = /* @__PURE__ */ new Set();
|
|
40539
|
+
for (const { variable } of exports) {
|
|
40540
|
+
if (variables.has(variable)) {
|
|
40541
|
+
throw new CLIError("USAGE_ERROR", `Two secrets are mapped to ${variable}. Give each its own variable.`, ExitCode.USAGE_ERROR);
|
|
40542
|
+
}
|
|
40543
|
+
variables.add(variable);
|
|
40544
|
+
}
|
|
40545
|
+
return { command: [program, ...args], exports };
|
|
40546
|
+
}
|
|
40547
|
+
var RERAISED_SIGNALS = {
|
|
40548
|
+
SIGINT: true,
|
|
40549
|
+
SIGTERM: true,
|
|
40550
|
+
SIGHUP: true,
|
|
40551
|
+
SIGKILL: true,
|
|
40552
|
+
SIGALRM: true,
|
|
40553
|
+
SIGUSR2: true
|
|
40554
|
+
};
|
|
40555
|
+
var TC_CREDENTIAL_VARIABLES = ["TC_PRIVATE_KEY"];
|
|
40556
|
+
function exitAsCommand(outcome, program) {
|
|
40557
|
+
if (outcome.kind === "exited") return process.exit(outcome.code);
|
|
40558
|
+
if (outcome.kind === "signaled") {
|
|
40559
|
+
if (RERAISED_SIGNALS[outcome.signal]) process.kill(process.pid, outcome.signal);
|
|
40560
|
+
return process.exit(128 + (osConstants.signals[outcome.signal] ?? 0));
|
|
40561
|
+
}
|
|
40562
|
+
const reason = outcome.errno === "ENOENT" ? "command not found" : outcome.errno === "EACCES" ? "permission denied" : `cannot run (${outcome.errno ?? "unknown error"})`;
|
|
40563
|
+
process.stderr.write(`${CLI_NAME32} secrets run: ${safeInline(program)}: ${reason}
|
|
40564
|
+
`);
|
|
40565
|
+
return process.exit(outcome.errno === "ENOENT" ? 127 : 126);
|
|
40566
|
+
}
|
|
40329
40567
|
function registerSecretsCommand(program, openKeyAcquisition) {
|
|
40330
40568
|
const secrets = program.command("secrets").description("Encrypted secrets management");
|
|
40331
40569
|
const network = secrets.command("network").description("Manage the default secrets encryption network");
|
|
@@ -40493,66 +40731,23 @@ function registerSecretsCommand(program, openKeyAcquisition) {
|
|
|
40493
40731
|
try {
|
|
40494
40732
|
const globalOpts = cmd.optsWithGlobals();
|
|
40495
40733
|
const ctx = await ProfileManager.resolveContext(globalOpts);
|
|
40496
|
-
const
|
|
40497
|
-
const legacySpaceUri = await resolveSecretSpace(options.space, ctx.profile);
|
|
40498
|
-
const secretPath = resolveSecretPath2(name, scopeOptions).permissionPaths.vault;
|
|
40734
|
+
const target = await resolveSecretReadTarget(ctx, name, options);
|
|
40499
40735
|
if (options.output) await validatePrivateOutput(options.output, "Secret output");
|
|
40736
|
+
const secret = await readSecret({ ctx, host: globalOpts.host, target, options, openKeyAcquisition });
|
|
40737
|
+
const value = secret.value;
|
|
40500
40738
|
if (options.delegation) {
|
|
40501
|
-
const delegated = await resolveDelegatedSecretSource(
|
|
40502
|
-
options.delegation,
|
|
40503
|
-
secretPath,
|
|
40504
|
-
legacySpaceUri ?? SECRETS_SPACE2
|
|
40505
|
-
);
|
|
40506
|
-
const effectiveHost = globalOpts.host ?? delegated.delegation.host ?? ctx.host;
|
|
40507
|
-
const delegatedCtx = { ...ctx, host: effectiveHost };
|
|
40508
|
-
const local = effectiveLocal(await ProfileManager.getProfile(ctx.profile).catch(() => null), options);
|
|
40509
|
-
const scope = resolveSecretPath2(name, scopeOptions).scope;
|
|
40510
|
-
const node = await ensureSecretsNode(delegatedCtx, options);
|
|
40511
|
-
const value2 = await withSpinner(
|
|
40512
|
-
`Getting secret ${name}...`,
|
|
40513
|
-
() => readDelegatedSecretValue({
|
|
40514
|
-
node,
|
|
40515
|
-
delegation: delegated.delegation,
|
|
40516
|
-
delegationCid: delegated.delegation.cid,
|
|
40517
|
-
permissions: delegated.permissions,
|
|
40518
|
-
secretPath,
|
|
40519
|
-
space: legacySpaceUri ?? SECRETS_SPACE2,
|
|
40520
|
-
name,
|
|
40521
|
-
...scope === void 0 ? {} : { scope },
|
|
40522
|
-
local
|
|
40523
|
-
})
|
|
40524
|
-
);
|
|
40525
40739
|
if (options.output) {
|
|
40526
|
-
await writePrivateOutput(options.output,
|
|
40740
|
+
await writePrivateOutput(options.output, value, "Secret output");
|
|
40527
40741
|
outputJson({ name, written: options.output });
|
|
40528
40742
|
return;
|
|
40529
40743
|
}
|
|
40530
40744
|
if (options.raw) {
|
|
40531
|
-
process.stdout.write(
|
|
40745
|
+
process.stdout.write(value);
|
|
40532
40746
|
return;
|
|
40533
40747
|
}
|
|
40534
|
-
outputJson({ name, value
|
|
40748
|
+
outputJson({ name, value });
|
|
40535
40749
|
return;
|
|
40536
40750
|
}
|
|
40537
|
-
const privateKey = authOptions(options)?.privateKey;
|
|
40538
|
-
const spaceUri = privateKey !== void 0 && options.space !== void 0 && !options.space.startsWith("tinycloud:") ? options.space : legacySpaceUri;
|
|
40539
|
-
const result = await invokeCanonicalSecretGet({
|
|
40540
|
-
ctx,
|
|
40541
|
-
name,
|
|
40542
|
-
...scopeOptions?.scope === void 0 ? {} : { scope: scopeOptions.scope },
|
|
40543
|
-
...spaceUri === void 0 ? {} : { space: spaceUri },
|
|
40544
|
-
options,
|
|
40545
|
-
label: `Getting secret ${name}...`,
|
|
40546
|
-
openKeyAcquisition
|
|
40547
|
-
});
|
|
40548
|
-
if (result.status !== "ok") {
|
|
40549
|
-
try {
|
|
40550
|
-
throwCanonicalSecretGetError(result, name);
|
|
40551
|
-
} catch (error) {
|
|
40552
|
-
throw withOperationWarnings(error, result.warnings);
|
|
40553
|
-
}
|
|
40554
|
-
}
|
|
40555
|
-
const value = result.output.value;
|
|
40556
40751
|
try {
|
|
40557
40752
|
if (options.output) {
|
|
40558
40753
|
await writePrivateOutput(options.output, value, "Secret output");
|
|
@@ -40563,9 +40758,47 @@ function registerSecretsCommand(program, openKeyAcquisition) {
|
|
|
40563
40758
|
outputJson({ name, value });
|
|
40564
40759
|
}
|
|
40565
40760
|
} catch (error) {
|
|
40566
|
-
throw withOperationWarnings(error,
|
|
40761
|
+
throw withOperationWarnings(error, secret.warnings);
|
|
40567
40762
|
}
|
|
40568
|
-
outputWarnings(operationWarnings(
|
|
40763
|
+
outputWarnings(operationWarnings(secret.warnings));
|
|
40764
|
+
} catch (error) {
|
|
40765
|
+
return handleError(error);
|
|
40766
|
+
}
|
|
40767
|
+
});
|
|
40768
|
+
secrets.command("run [names...]").description("Run a command with secrets in its environment").usage("[options] [names...] -- <command> [args...]").option(
|
|
40769
|
+
"--map <NAME=ENV_VAR>",
|
|
40770
|
+
"Give secret NAME to the command as environment variable ENV_VAR (repeatable)",
|
|
40771
|
+
(value, previous) => [...previous ?? [], value]
|
|
40772
|
+
).option("--scope <scope>", "Logical secret scope").option("--space <name|uri>", "Target a non-default secrets space (short name or full URI)").option("--delegation <source>", "Delegation file path or imported profile name").option("--private-key <hex>", "Ethereum private key (or set TC_PRIVATE_KEY)").action(async (operands, options, cmd) => {
|
|
40773
|
+
try {
|
|
40774
|
+
const plan = secretRunPlan(cmd, operands, options.map ?? []);
|
|
40775
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
40776
|
+
const ctx = await ProfileManager.resolveContext(globalOpts);
|
|
40777
|
+
const targets = [];
|
|
40778
|
+
for (const name of new Set(plan.exports.map((entry) => entry.name))) {
|
|
40779
|
+
targets.push(await resolveSecretReadTarget(ctx, name, options));
|
|
40780
|
+
}
|
|
40781
|
+
const values = /* @__PURE__ */ new Map();
|
|
40782
|
+
let warnings = [];
|
|
40783
|
+
for (const target of targets) {
|
|
40784
|
+
const secret = await readSecret({ ctx, host: globalOpts.host, target, options, openKeyAcquisition });
|
|
40785
|
+
if (secret.value.includes("\0")) {
|
|
40786
|
+
throw new CLIError(
|
|
40787
|
+
"SECRET_NOT_EXPORTABLE",
|
|
40788
|
+
`Secret "${target.name}" contains a NUL character, so it can't be put in an environment variable. The command wasn't started.`,
|
|
40789
|
+
ExitCode.ERROR
|
|
40790
|
+
);
|
|
40791
|
+
}
|
|
40792
|
+
values.set(target.name, secret.value);
|
|
40793
|
+
warnings = mergeWarnings(warnings, secret.warnings ?? []);
|
|
40794
|
+
}
|
|
40795
|
+
outputWarnings(operationWarnings(warnings));
|
|
40796
|
+
await closeReplication();
|
|
40797
|
+
const env = { ...process.env };
|
|
40798
|
+
for (const variable of TC_CREDENTIAL_VARIABLES) delete env[variable];
|
|
40799
|
+
for (const entry of plan.exports) env[entry.variable] = values.get(entry.name);
|
|
40800
|
+
values.clear();
|
|
40801
|
+
exitAsCommand(await runCommand(plan.command, env), plan.command[0]);
|
|
40569
40802
|
} catch (error) {
|
|
40570
40803
|
return handleError(error);
|
|
40571
40804
|
}
|
|
@@ -41027,7 +41260,7 @@ async function writeShareOutput(directory, filename, bytes, force) {
|
|
|
41027
41260
|
init_profiles();
|
|
41028
41261
|
|
|
41029
41262
|
// src/share/html-folder.ts
|
|
41030
|
-
import { constants as constants2, existsSync } from "fs";
|
|
41263
|
+
import { constants as constants2, existsSync as existsSync2 } from "fs";
|
|
41031
41264
|
import { lstat as lstat11, open as open14, readdir as readdir7, realpath as realpath3, stat as stat7 } from "fs/promises";
|
|
41032
41265
|
import { basename as basename5, dirname as dirname9, isAbsolute, join as join19, relative as relativePath, resolve as resolve7, sep as sep4 } from "path";
|
|
41033
41266
|
|
|
@@ -41965,7 +42198,7 @@ function isRaceError(error) {
|
|
|
41965
42198
|
}
|
|
41966
42199
|
var PROC_FD = "/proc/self/fd";
|
|
41967
42200
|
async function linuxDescriptorPath(fd) {
|
|
41968
|
-
if (process.platform !== "linux" || !
|
|
42201
|
+
if (process.platform !== "linux" || !existsSync2(PROC_FD)) return void 0;
|
|
41969
42202
|
return realpath3(`${PROC_FD}/${fd}`);
|
|
41970
42203
|
}
|
|
41971
42204
|
async function parentChainIsRealDirectories(root, path) {
|
|
@@ -43602,11 +43835,11 @@ function plural(count, label) {
|
|
|
43602
43835
|
init_theme();
|
|
43603
43836
|
init_errors();
|
|
43604
43837
|
import { execSync } from "child_process";
|
|
43605
|
-
import { readFileSync as
|
|
43838
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
43606
43839
|
var PACKAGE_NAME = "@tinycloud/cli";
|
|
43607
43840
|
function getCurrentVersion() {
|
|
43608
43841
|
const pkg = JSON.parse(
|
|
43609
|
-
|
|
43842
|
+
readFileSync3(new URL("../package.json", import.meta.url), "utf-8")
|
|
43610
43843
|
);
|
|
43611
43844
|
return pkg.version;
|
|
43612
43845
|
}
|