synthesisui 0.16.58 → 0.16.59

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.
@@ -1,6 +1,6 @@
1
1
  import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
2
- import { basename, join, relative } from "node:path";
3
- import { readToken, resolveRegistry } from "../config.js";
2
+ import { basename, dirname, join, relative } from "node:path";
3
+ import { readCredentials, readToken, resolveRegistry, sameRegistry, } from "../config.js";
4
4
  import { isNearDuplicate, isNeutral, lightness, } from "../doctor/color-distance.js";
5
5
  import { emptyTally, internalSpecifiers, scanComponentsInto, tallyToInventory, } from "../doctor/components-scan.js";
6
6
  import { crosswalk, observedRules } from "../doctor/crosswalk.js";
@@ -894,8 +894,12 @@ export async function runImport(opts) {
894
894
  summarize(census);
895
895
  if (!opts.census)
896
896
  await sayIfWorkspace(root);
897
- const out = join(root, "_synthesisui", "census.json");
898
- await mkdir(join(root, "_synthesisui"), { recursive: true });
897
+ // A census handed to us is written BACK TO ITSELF. Deriving the path from the
898
+ // root instead planted a second census at the repo root when the real one
899
+ // lived in `packages/ui/_synthesisui/` - two files, silently disagreeing
900
+ // about which import happened (dono, 31/07).
901
+ const out = opts.census ?? join(root, "_synthesisui", "census.json");
902
+ await mkdir(dirname(out), { recursive: true });
899
903
  await writeFile(out, `${JSON.stringify(census, null, 2)}\n`, "utf8");
900
904
  console.log("");
901
905
  console.log(body(`Written to ${paint.strong(relative(root, out))}`));
@@ -944,6 +948,20 @@ export async function runImport(opts) {
944
948
  return;
945
949
  }
946
950
  const base = resolveRegistry(opts.registry);
951
+ // A token belongs to the host that issued it. Sending it anywhere else earns
952
+ // a 401 that describes the wrong problem entirely.
953
+ const creds = await readCredentials();
954
+ if (creds && !sameRegistry(creds.registry, base)) {
955
+ console.log("");
956
+ console.log(body(`You are logged in to ${paint.strong(creds.registry ?? "another registry")}, and this would go to ${paint.strong(base)}.`));
957
+ console.log(body("The census is on disk. Either name the one you meant:"));
958
+ console.log("");
959
+ console.log(body(` synthesisui import --census ${out} --registry ${creds.registry}`));
960
+ console.log(body("or log in to this one:"));
961
+ console.log(body(` synthesisui login --registry ${base}`));
962
+ console.log("");
963
+ return;
964
+ }
947
965
  const res = await fetch(`${base}/api/onboarding/import`, {
948
966
  method: "POST",
949
967
  headers: {
@@ -968,7 +986,7 @@ export async function runImport(opts) {
968
986
  console.log(body("Your session has expired. The census is on disk."));
969
987
  console.log("");
970
988
  console.log(body(` ${paint.strong("synthesisui login")}`));
971
- console.log(body(` synthesisui import --census ${relative(root, out)}${chosen ? ` --name "${chosen}"` : ""}`));
989
+ console.log(body(` synthesisui import --census ${out}${chosen ? ` --name "${chosen}"` : ""}`));
972
990
  console.log("");
973
991
  return;
974
992
  }
package/dist/config.js CHANGED
@@ -17,6 +17,33 @@ export const credentialsPath = join(homedir(), ".synthesisui", "credentials.json
17
17
  * Reads the saved token, if any. Optional for now (open gate); the device-flow
18
18
  * is what writes it. Sent as a Bearer header when present.
19
19
  */
20
+ /**
21
+ * The token AND the registry it was issued for.
22
+ *
23
+ * They were always written together and never read together, so a token minted
24
+ * by `login --registry http://localhost:3000` was sent to production, which
25
+ * refused it with a 401 that read as "your session expired" (dono, 31/07). A
26
+ * session cannot expire on a host that never issued it.
27
+ */
28
+ export async function readCredentials() {
29
+ try {
30
+ const raw = await readFile(credentialsPath, "utf8");
31
+ const parsed = JSON.parse(raw);
32
+ if (!parsed.token)
33
+ return null;
34
+ return { token: parsed.token, registry: parsed.registry ?? null };
35
+ }
36
+ catch {
37
+ return null;
38
+ }
39
+ }
40
+ /** Two registry URLs, compared the way a person means them. */
41
+ export function sameRegistry(a, b) {
42
+ if (!a || !b)
43
+ return true;
44
+ const norm = (u) => u.trim().replace(/\/+$/, "").toLowerCase();
45
+ return norm(a) === norm(b);
46
+ }
20
47
  export async function readToken() {
21
48
  try {
22
49
  const raw = await readFile(credentialsPath, "utf8");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synthesisui",
3
- "version": "0.16.58",
3
+ "version": "0.16.59",
4
4
  "description": "Bring SynthesisUI design systems into any project - tokens, typed components, whole pages and an agent-ready CLAUDE.md manifest.",
5
5
  "type": "module",
6
6
  "bin": {