@unoverse-platform/studio 0.1.61 → 0.1.63

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/local/plugin.ts CHANGED
@@ -279,6 +279,31 @@ export function localStudioHost(): Plugin {
279
279
  return json(res, {});
280
280
  }
281
281
 
282
+ /**
283
+ * THE WORKSPACE'S OWN UNIVERSE, for the Live preview. unoverse.yaml (written
284
+ * by `unoverse deploy studio`, committed with the repo) names where this
285
+ * workspace ships; failing that, a machine signed in to exactly one universe
286
+ * has answered the question too. This is the "future work" liveUniverseUrl's
287
+ * stub promised: the universe comes from the workspace, never a browser
288
+ * store nobody can clear.
289
+ */
290
+ case path === "/local/universe": {
291
+ try {
292
+ const { readFileSync } = await import("node:fs");
293
+ const y = readFileSync(resolve(projectRoot, "unoverse.yaml"), "utf8");
294
+ const m = y.match(/^universe:\s*(\S+)\s*$/m);
295
+ if (m) return json(res, { universe: m[1] });
296
+ } catch { /* no file: fall through to the session */ }
297
+ try {
298
+ const { readFileSync } = await import("node:fs");
299
+ const { homedir } = await import("node:os");
300
+ const { join } = await import("node:path");
301
+ const origins = Object.keys(JSON.parse(readFileSync(join(homedir(), ".unoverse", "sessions.json"), "utf8")));
302
+ if (origins.length === 1) return json(res, { universe: origins[0] });
303
+ } catch { /* signed out */ }
304
+ return json(res, { universe: "" });
305
+ }
306
+
282
307
  case path === "/dev/orgs":
283
308
  return json(res, { orgs: c.themeOrgs() });
284
309
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unoverse-platform/studio",
3
- "version": "0.1.61",
3
+ "version": "0.1.63",
4
4
  "type": "module",
5
5
  "description": "Unoverse Studio: the local authoring app. Reads your own rx/ folder, no backend.",
6
6
  "scripts": {
@@ -259,7 +259,26 @@ export function TemplatesView({
259
259
  // The live server: the signed-in universe, else the local dev platform (see the
260
260
  // CONN_DEFAULTS note). A universe URL is already an https origin; the bare local
261
261
  // fallback gets http.
262
- const universeUrl = liveUniverseUrl();
262
+ /**
263
+ * THE WORKSPACE NAMES THE LIVE SERVER. unoverse.yaml (written by deploy) or the
264
+ * single signed-in session, served by the local host (/local/universe) — so Live
265
+ * previews target the universe this workspace actually ships to, and an auth
266
+ * message can name the RIGHT server instead of sending someone to log in to
267
+ * localhost (observed live 2026-08-21). Canvas keeps its own liveUniverseUrl.
268
+ */
269
+ const [wsUniverse, setWsUniverse] = useState<string>("");
270
+ useEffect(() => {
271
+ if (!hasSourceAccess) return;
272
+ let live = true;
273
+ authedFetch("/local/universe")
274
+ .then((r) => r.json())
275
+ .then((d) => live && setWsUniverse(typeof d?.universe === "string" ? d.universe : ""))
276
+ .catch(() => live && setWsUniverse(""));
277
+ return () => {
278
+ live = false;
279
+ };
280
+ }, []);
281
+ const universeUrl = liveUniverseUrl() ?? (wsUniverse || null);
263
282
  const liveServer = universeUrl ?? LOCAL_DEV_SERVER;
264
283
  const liveBase = liveServer.includes("://") ? liveServer : `http://${liveServer}`;
265
284
  useEffect(() => {
@@ -868,7 +887,7 @@ export function TemplatesView({
868
887
  come from the selected app's manifest binding (no manual entry). */}
869
888
  {(
870
889
  [
871
- { label: "Server", value: liveServer, note: universeUrl ? "signed-in universe" : "local dev (no universe connected)" },
890
+ { label: "Server", value: liveServer, note: universeUrl ? "your workspace\u2019s universe" : "local dev (no universe configured \u2014 unoverse login, or deploy once)" },
872
891
  { label: "Workflow", value: binding?.workflow ?? "— no app binding", note: "from app" },
873
892
  { label: "Trigger node", value: binding?.trigger ?? "—", note: "from app" },
874
893
  ]