synthesisui 0.16.57 → 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.
- package/dist/commands/import.js +34 -4
- package/dist/config.js +27 -0
- package/package.json +1 -1
package/dist/commands/import.js
CHANGED
|
@@ -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
|
-
|
|
898
|
-
|
|
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: {
|
|
@@ -960,6 +978,18 @@ export async function runImport(opts) {
|
|
|
960
978
|
.catch(() => null)
|
|
961
979
|
: null;
|
|
962
980
|
console.log("");
|
|
981
|
+
// A 401 is not a refusal of the census, it is an expired session - and
|
|
982
|
+
// saying "HTTP 401" at the end of a long read leaves the person guessing at
|
|
983
|
+
// which of the two it was (dono, 31/07). A stale token gets past the
|
|
984
|
+
// `readToken` guard above and only fails here.
|
|
985
|
+
if (res?.status === 401) {
|
|
986
|
+
console.log(body("Your session has expired. The census is on disk."));
|
|
987
|
+
console.log("");
|
|
988
|
+
console.log(body(` ${paint.strong("synthesisui login")}`));
|
|
989
|
+
console.log(body(` synthesisui import --census ${out}${chosen ? ` --name "${chosen}"` : ""}`));
|
|
990
|
+
console.log("");
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
963
993
|
console.log(body(res
|
|
964
994
|
? `The registry refused it (HTTP ${res.status})${detail ? `: ${detail}` : "."}`
|
|
965
995
|
: "Could not reach the registry. The census is on disk - try again later."));
|
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