@topolo/cli 0.8.9 → 0.9.1

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 +56 -6
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -730,7 +730,7 @@ function prepareTopoloActionUploadInput(contractValue, content, input2, options)
730
730
  if (bytes.byteLength > contract.maxBytes) {
731
731
  throw new TopoloSdkError("upload_too_large", `Upload content exceeds the ${contract.maxBytes}-byte action limit.`);
732
732
  }
733
- return mapUploadInput(contract, bytesToBase64(bytes), input2, options);
733
+ return mapUploadInput(contract, encodeTopoloActionBase64(bytes), input2, options);
734
734
  }
735
735
  function prepareTopoloActionBase64UploadInput(contractValue, contentBase64, input2, options) {
736
736
  const contract = parseTopoloActionUploadContract(contractValue);
@@ -866,7 +866,7 @@ function requiredField(value, name) {
866
866
  function matchesContentType(contentType, accepted) {
867
867
  return accepted.some((candidate) => candidate === "*/*" || candidate === contentType || candidate.endsWith("/*") && contentType.startsWith(candidate.slice(0, -1)));
868
868
  }
869
- function bytesToBase64(bytes) {
869
+ function encodeTopoloActionBase64(bytes) {
870
870
  let binary = "";
871
871
  const chunkSize = 32768;
872
872
  for (let offset = 0; offset < bytes.length; offset += chunkSize) {
@@ -1043,7 +1043,20 @@ var TopoloClient = class _TopoloClient {
1043
1043
  throw err;
1044
1044
  }
1045
1045
  const contentType = res.headers.get("Content-Type") ?? "";
1046
- const parsed = contentType.includes("application/json") ? await res.json().catch(() => null) : await res.text().catch(() => null);
1046
+ const normalizedContentType = contentType.split(";", 1)[0]?.trim().toLowerCase() ?? "";
1047
+ let parsed;
1048
+ if (normalizedContentType === "application/json" || normalizedContentType.endsWith("+json")) {
1049
+ parsed = await res.json().catch(() => null);
1050
+ } else if (!res.ok || !normalizedContentType || normalizedContentType.startsWith("text/")) {
1051
+ parsed = await res.text().catch(() => null);
1052
+ } else {
1053
+ const bytes = new Uint8Array(await res.arrayBuffer());
1054
+ parsed = {
1055
+ contentType: normalizedContentType,
1056
+ contentLength: bytes.byteLength,
1057
+ contentBase64: encodeTopoloActionBase64(bytes)
1058
+ };
1059
+ }
1047
1060
  if (!res.ok) {
1048
1061
  const durationMs = Date.now() - startedAt;
1049
1062
  const message2 = describeError(parsed, `HTTP ${res.status}`);
@@ -2687,6 +2700,7 @@ var TopoloOAuth2 = class {
2687
2700
  return parsed;
2688
2701
  }
2689
2702
  };
2703
+ var TOPOLO_RUNTIME_ENVIRONMENTS = ["production", "staging", "development", "local"];
2690
2704
  var TOPOLO_ENVIRONMENT_SERVICE_URLS = {
2691
2705
  production: {
2692
2706
  auth: "https://auth.topolo.app",
@@ -2747,6 +2761,7 @@ function topoloServiceOrigins2(serviceUrls, environment) {
2747
2761
  ])
2748
2762
  );
2749
2763
  }
2764
+ var TOPOLO_ENVIRONMENTS = TOPOLO_RUNTIME_ENVIRONMENTS;
2750
2765
  function contextKey(contextType, organizationId) {
2751
2766
  return contextType === "organization" && organizationId ? `org:${organizationId}` : "personal";
2752
2767
  }
@@ -3041,6 +3056,19 @@ function resolvedProfileConfig(config, environment = selectedEnvironment()) {
3041
3056
  }
3042
3057
 
3043
3058
  // src/config.ts
3059
+ async function authenticatedEnvironments(configOrPromise = readConfig()) {
3060
+ const config = await configOrPromise;
3061
+ const found = /* @__PURE__ */ new Set();
3062
+ if (config.credential) found.add("production");
3063
+ for (const environment of TOPOLO_ENVIRONMENTS) {
3064
+ const profile = config.profiles?.[environment];
3065
+ if (!profile) continue;
3066
+ if (profile.credential || Object.keys(profile.contexts ?? {}).length > 0) {
3067
+ found.add(environment);
3068
+ }
3069
+ }
3070
+ return TOPOLO_ENVIRONMENTS.filter((environment) => found.has(environment));
3071
+ }
3044
3072
  function environmentLabel(environment = selectedEnvironment()) {
3045
3073
  return environment;
3046
3074
  }
@@ -5261,6 +5289,8 @@ Workspace: ${workspace.name} (${workspace.id})${workspace.isDefault ? "\nDefault
5261
5289
  // src/index.ts
5262
5290
  installOutputErrorHandlers();
5263
5291
  var program = new Command();
5292
+ var environmentArgSeen = false;
5293
+ var inheritedEnvironment = process.env.TOPOLO_ENV?.trim();
5264
5294
  var argv;
5265
5295
  try {
5266
5296
  argv = consumeEnvironmentArg(process.argv);
@@ -5269,13 +5299,31 @@ try {
5269
5299
  `);
5270
5300
  process.exit(1);
5271
5301
  }
5302
+ var environmentWasStated = Boolean(inheritedEnvironment) || environmentArgSeen;
5272
5303
  program.name("topolo").description(
5273
5304
  "Public Topolo CLI for customer identity, organization context, applications, resources, and actions."
5274
5305
  ).version(CLI_VERSION).option("--env <environment>", "Topolo environment: production, staging, development, or local");
5275
- program.hook("preAction", (thisCommand) => {
5306
+ program.hook("preAction", async (thisCommand, actionCommand) => {
5276
5307
  const opts = thisCommand.opts();
5277
- if (!opts.env) return;
5278
- process.env.TOPOLO_ENV = normalizeEnvironment(opts.env);
5308
+ if (opts.env) process.env.TOPOLO_ENV = normalizeEnvironment(opts.env);
5309
+ if (opts.env || environmentWasStated) return;
5310
+ const authenticated = await authenticatedEnvironments();
5311
+ if (authenticated.length < 2) return;
5312
+ const path = [];
5313
+ for (let node = actionCommand; node && node !== program; node = node.parent) {
5314
+ path.unshift(node.name());
5315
+ }
5316
+ process.stderr.write(
5317
+ `This machine is signed in to ${authenticated.length} Topolo environments (${authenticated.join(", ")}), so the environment is no longer safe to assume.
5318
+
5319
+ State it explicitly:
5320
+ topolo --env <${authenticated.join("|")}> ${path.join(" ")} ...
5321
+
5322
+ Or set it once for the whole session:
5323
+ export TOPOLO_ENV=<${authenticated.join("|")}>
5324
+ `
5325
+ );
5326
+ process.exit(2);
5279
5327
  });
5280
5328
  registerAuthCommands(program);
5281
5329
  registerWhoamiCommand(program);
@@ -5307,11 +5355,13 @@ function consumeEnvironmentArg(argv2) {
5307
5355
  throw new Error("--env requires production, staging, development, or local.");
5308
5356
  }
5309
5357
  process.env.TOPOLO_ENV = normalizeEnvironment(value);
5358
+ environmentArgSeen = true;
5310
5359
  i += 1;
5311
5360
  continue;
5312
5361
  }
5313
5362
  if (arg.startsWith("--env=")) {
5314
5363
  process.env.TOPOLO_ENV = normalizeEnvironment(arg.slice("--env=".length));
5364
+ environmentArgSeen = true;
5315
5365
  continue;
5316
5366
  }
5317
5367
  next.push(arg);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@topolo/cli",
3
- "version": "0.8.9",
4
- "topoloPublishedVersion": "0.8.9",
3
+ "version": "0.9.1",
4
+ "topoloPublishedVersion": "0.9.1",
5
5
  "description": "Public command-line interface for Topolo customer organizations, developers, and agents.",
6
6
  "license": "UNLICENSED",
7
7
  "author": "Topolo",
@@ -25,8 +25,8 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@modelcontextprotocol/sdk": "^1.0.0",
28
- "@topolo/mcp": "0.11.7",
29
- "@topolo/sdk": "0.11.7",
28
+ "@topolo/mcp": "0.11.8",
29
+ "@topolo/sdk": "0.11.8",
30
30
  "commander": "^12.1.0"
31
31
  },
32
32
  "devDependencies": {