@tinycloud/cli 1.3.0-beta.36 → 1.3.0-beta.38

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/index.js CHANGED
@@ -122,7 +122,7 @@ import {
122
122
  tinycloudConfigPath,
123
123
  tinycloudHomePath
124
124
  } from "@tinycloud/operations/state";
125
- var CONFIG_DIR, PROFILES_DIR, CONFIG_FILE, DEFAULT_HOST, DEFAULT_PROFILE, PROFILE_COMMIT_LOCK_TIMEOUT_MS, ExitCode;
125
+ var CONFIG_DIR, PROFILES_DIR, CONFIG_FILE, DEFAULT_HOST, DEFAULT_PROFILE, PROFILE_COMMIT_LOCK_TIMEOUT_MS, ExitCode, OPENKEY_SPACE_SETUP_RETRY_HINT;
126
126
  var init_constants = __esm({
127
127
  "src/config/constants.ts"() {
128
128
  "use strict";
@@ -148,6 +148,36 @@ var init_constants = __esm({
148
148
  /** Interrupted by SIGINT/SIGTERM (`CANCELLED`). */
149
149
  CANCELLED: 130
150
150
  };
151
+ OPENKEY_SPACE_SETUP_RETRY_HINT = "Wait a minute and retry; approving again in OpenKey re-runs the setup.";
152
+ }
153
+ });
154
+
155
+ // src/output/safe-text.ts
156
+ function escape(match) {
157
+ return `\\u{${match.codePointAt(0).toString(16)}}`;
158
+ }
159
+ function safeBlock(text) {
160
+ return text.replace(UNSAFE_BLOCK, escape);
161
+ }
162
+ function safeInline(text) {
163
+ return text.replace(UNSAFE_INLINE, escape);
164
+ }
165
+ function safeClipped(text, max = ECHO_FIELD_MAX) {
166
+ const escaped = Array.from(safeInline(text));
167
+ return escaped.length <= max ? escaped.join("") : `${escaped.slice(0, max).join("")}\u2026`;
168
+ }
169
+ function safeJsonStringify(value, space) {
170
+ const text = JSON.stringify(value, null, space);
171
+ return text === void 0 ? text : text.replace(JSON_UNSAFE, (character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`);
172
+ }
173
+ var UNSAFE_BLOCK, UNSAFE_INLINE, ECHO_FIELD_MAX, JSON_UNSAFE;
174
+ var init_safe_text = __esm({
175
+ "src/output/safe-text.ts"() {
176
+ "use strict";
177
+ UNSAFE_BLOCK = /[\u0000-\u0008\u000b-\u001f\u007f-\u009f\u061c\u200b-\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069\ufeff]/g;
178
+ UNSAFE_INLINE = /[\u0000-\u001f\u007f-\u009f\u061c\u200b-\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069\ufeff]/g;
179
+ ECHO_FIELD_MAX = 80;
180
+ JSON_UNSAFE = /[\u007f-\u009f\u061c\u200b-\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069\ufeff]/g;
151
181
  }
152
182
  });
153
183
 
@@ -235,12 +265,12 @@ function outputError(code4, message, hint, details = {}) {
235
265
  const { meta, warnings = [], setup, recovery, progress } = details;
236
266
  if (!shouldOutputJson()) {
237
267
  process.stderr.write(
238
- `${theme.error("\u2717")} ${theme.label(code4)}: ${message}
268
+ `${theme.error("\u2717")} ${theme.label(safeInline(code4))}: ${safeBlock(message)}
239
269
  `
240
270
  );
241
271
  if (hint) {
242
272
  for (const line of hint.split("\n")) {
243
- process.stderr.write(` ${theme.hint(line)}
273
+ process.stderr.write(` ${theme.hint(safeBlock(line))}
244
274
  `);
245
275
  }
246
276
  }
@@ -256,13 +286,13 @@ function outputError(code4, message, hint, details = {}) {
256
286
  if (progress) payload.error.progress = progress;
257
287
  if (meta) payload.error.meta = meta;
258
288
  if (warnings.length > 0) payload.error.warnings = warnings;
259
- process.stderr.write(JSON.stringify(payload, null, 2) + "\n");
289
+ process.stderr.write(safeJsonStringify(payload, 2) + "\n");
260
290
  }
261
291
  }
262
292
  function outputWarnings(warnings) {
263
293
  const combined = mergeWarnings(drainWarnings(), operationWarnings(warnings));
264
294
  if (combined.length === 0) return;
265
- process.stderr.write(shouldOutputJson() ? `${JSON.stringify({ warnings: combined })}
295
+ process.stderr.write(shouldOutputJson() ? `${safeJsonStringify({ warnings: combined })}
266
296
  ` : `${theme.warn("!")} ${warningLine(combined)}
267
297
  `);
268
298
  }
@@ -290,6 +320,7 @@ var WARNING_CODE, WARNING_REASON, DELEGATION_CID, JSON_REQUESTED;
290
320
  var init_formatter = __esm({
291
321
  "src/output/formatter.ts"() {
292
322
  "use strict";
323
+ init_safe_text();
293
324
  init_theme();
294
325
  init_warnings();
295
326
  WARNING_CODE = /^[A-Z][A-Z_]{0,63}$/;
@@ -746,6 +777,13 @@ var init_types = __esm({
746
777
 
747
778
  // src/lib/space.ts
748
779
  import { CLI_NAME as CLI_NAME5 } from "@tinycloud/operations/cli-name";
780
+ function invalidSpaceError(input) {
781
+ return new CLIError(
782
+ "INVALID_SPACE",
783
+ `Invalid space "${safeClipped(input)}". Use a short name ([A-Za-z0-9_-]) or a full tinycloud:... URI.`,
784
+ ExitCode.USAGE_ERROR
785
+ );
786
+ }
749
787
  function canonicalizeAddress(address) {
750
788
  const trimmed = address.trim();
751
789
  return trimmed.startsWith("0x") ? `0x${trimmed.slice(2).toLowerCase()}` : trimmed.toLowerCase();
@@ -803,22 +841,10 @@ async function resolveSpaceUri(input, profileName, options = {}) {
803
841
  if (!effective) return void 0;
804
842
  if (effective.startsWith("tinycloud:")) {
805
843
  const parsed = parseSpaceUri(effective);
806
- if (!parsed) {
807
- throw new CLIError(
808
- "INVALID_SPACE",
809
- `Invalid space "${effective}". Use a short name ([A-Za-z0-9_-]) or a full tinycloud:... URI.`,
810
- ExitCode.USAGE_ERROR
811
- );
812
- }
844
+ if (!parsed) throw invalidSpaceError(effective);
813
845
  return buildSpaceUri(parsed.owner, parsed.name);
814
846
  }
815
- if (!/^[A-Za-z0-9_-]+$/.test(effective)) {
816
- throw new CLIError(
817
- "INVALID_SPACE",
818
- `Invalid space "${effective}". Use a short name ([A-Za-z0-9_-]) or a full tinycloud:... URI.`,
819
- ExitCode.USAGE_ERROR
820
- );
821
- }
847
+ if (!/^[A-Za-z0-9_-]+$/.test(effective)) throw invalidSpaceError(effective);
822
848
  const session = await ProfileManager.getSession(profileName);
823
849
  const address = resolveAddress(profile, session);
824
850
  const chainId = resolveChainId(profile, session);
@@ -829,6 +855,7 @@ var init_space = __esm({
829
855
  "use strict";
830
856
  init_errors();
831
857
  init_constants();
858
+ init_safe_text();
832
859
  init_profiles();
833
860
  }
834
861
  });
@@ -7266,17 +7293,25 @@ async function isRootAuthority(spaceUri, profileName) {
7266
7293
  const selfAddr = await resolveLocalAddress(profile, profileName);
7267
7294
  return selfAddr !== null && selfAddr === ownerAddr;
7268
7295
  }
7296
+ async function primarySpaceUri(profileName) {
7297
+ const session = await ProfileManager.getSession(profileName);
7298
+ if (typeof session?.spaceId === "string" && session.spaceId !== "") return session.spaceId;
7299
+ const profile = await ProfileManager.getProfile(profileName);
7300
+ return typeof profile.spaceId === "string" && profile.spaceId !== "" ? profile.spaceId : void 0;
7301
+ }
7269
7302
  function spaceNameFromUri(spaceUri) {
7270
7303
  return spaceUri.slice(spaceUri.lastIndexOf(":") + 1);
7271
7304
  }
7272
- async function unhostedSpaceError(error, spaceUri, profileName) {
7273
- if (!spaceUri) return null;
7305
+ async function unhostedSpaceError(error, requestedSpaceUri, profileName) {
7274
7306
  const status = error.meta?.status;
7275
7307
  const isUnhosted = status === 404 && /space not found/i.test(error.message);
7276
7308
  if (!isUnhosted) return null;
7309
+ const spaceUri = requestedSpaceUri ?? await primarySpaceUri(profileName);
7310
+ if (!spaceUri) return null;
7277
7311
  const spaceName = spaceNameFromUri(spaceUri);
7278
7312
  const owner = await isRootAuthority(spaceUri, profileName);
7279
- const hint = owner ? [
7313
+ const openKeyOwner = owner && resolveProfilePosture(await ProfileManager.getProfile(profileName)) === "owner-openkey";
7314
+ const hint = openKeyOwner ? `OpenKey is still setting up your space. ${OPENKEY_SPACE_SETUP_RETRY_HINT}` : owner ? [
7280
7315
  "You are the owner. Host it once:",
7281
7316
  ` ${CLI_NAME10} space host ${spaceName}`,
7282
7317
  "Then retry."