@floomhq/floom 1.0.29 → 1.0.31
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/cli.js +6 -4
- package/dist/config.js +39 -1
- package/dist/doctor.js +16 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -654,7 +654,7 @@ function sleep(ms, signal) {
|
|
|
654
654
|
}, { once: true });
|
|
655
655
|
});
|
|
656
656
|
}
|
|
657
|
-
async function watch(intervalSeconds) {
|
|
657
|
+
async function watch(intervalSeconds, target, once) {
|
|
658
658
|
const cfg = await readConfig();
|
|
659
659
|
if (!cfg) {
|
|
660
660
|
throw new FloomError("Not signed in.", `Run \`${CLI_COMMAND} login\` before \`${CLI_COMMAND} watch\`, or use \`${CLI_COMMAND} add <link>\` without an account.`);
|
|
@@ -671,9 +671,11 @@ async function watch(intervalSeconds) {
|
|
|
671
671
|
};
|
|
672
672
|
process.on("SIGINT", stop);
|
|
673
673
|
process.on("SIGTERM", stop);
|
|
674
|
-
process.stdout.write(`${symbols.bullet} Watching Floom sync every ${intervalSeconds}s. Press Ctrl-C to stop.\n`);
|
|
674
|
+
process.stdout.write(`${symbols.bullet} Watching Floom sync for ${target} every ${intervalSeconds}s. Press Ctrl-C to stop.\n`);
|
|
675
675
|
while (!controller.signal.aborted) {
|
|
676
|
-
await sync({ spinner: false, quietUnchanged: true });
|
|
676
|
+
await sync({ spinner: false, quietUnchanged: true, target });
|
|
677
|
+
if (once)
|
|
678
|
+
return;
|
|
677
679
|
await sleep(intervalSeconds * 1000, controller.signal);
|
|
678
680
|
}
|
|
679
681
|
}
|
|
@@ -827,7 +829,7 @@ async function main() {
|
|
|
827
829
|
});
|
|
828
830
|
return;
|
|
829
831
|
}
|
|
830
|
-
await watch(flags.intervalSeconds);
|
|
832
|
+
await watch(flags.intervalSeconds, flags.target, flags.once);
|
|
831
833
|
return;
|
|
832
834
|
}
|
|
833
835
|
case "delete":
|
package/dist/config.js
CHANGED
|
@@ -20,7 +20,7 @@ export async function readConfig() {
|
|
|
20
20
|
const parsed = JSON.parse(buf);
|
|
21
21
|
if (!parsed.accessToken || !parsed.refreshToken)
|
|
22
22
|
return null;
|
|
23
|
-
return parsed;
|
|
23
|
+
return refreshConfigIfNeeded(parsed);
|
|
24
24
|
}
|
|
25
25
|
catch (e) {
|
|
26
26
|
if (e.code === "ENOENT")
|
|
@@ -28,6 +28,44 @@ export async function readConfig() {
|
|
|
28
28
|
throw e;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
+
export async function refreshConfigIfNeeded(cfg, opts = {}) {
|
|
32
|
+
const now = Math.floor(Date.now() / 1000);
|
|
33
|
+
if (!opts.force && (typeof cfg.expiresAt !== "number" || cfg.expiresAt > now + 120))
|
|
34
|
+
return cfg;
|
|
35
|
+
try {
|
|
36
|
+
const refreshed = await refreshConfig(cfg);
|
|
37
|
+
await writeConfig(refreshed);
|
|
38
|
+
return refreshed;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return cfg;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function refreshConfig(cfg) {
|
|
45
|
+
const apiUrl = resolveApiUrl(cfg);
|
|
46
|
+
const res = await fetch(`${apiUrl}/api/auth/refresh`, {
|
|
47
|
+
method: "POST",
|
|
48
|
+
headers: { "content-type": "application/json" },
|
|
49
|
+
body: JSON.stringify({ refresh_token: cfg.refreshToken }),
|
|
50
|
+
});
|
|
51
|
+
if (!res.ok)
|
|
52
|
+
throw new Error(`refresh failed with ${res.status}`);
|
|
53
|
+
const data = (await res.json());
|
|
54
|
+
if (!data.access_token || !data.refresh_token)
|
|
55
|
+
throw new Error("refresh response missing tokens");
|
|
56
|
+
const expiresIn = Number(data.expires_in ?? "3600");
|
|
57
|
+
return {
|
|
58
|
+
...cfg,
|
|
59
|
+
accessToken: data.access_token,
|
|
60
|
+
refreshToken: data.refresh_token,
|
|
61
|
+
expiresAt: Math.floor(Date.now() / 1000) + (Number.isFinite(expiresIn) ? expiresIn : 3600),
|
|
62
|
+
...(typeof data.email === "string" || data.email === null
|
|
63
|
+
? { email: data.email }
|
|
64
|
+
: typeof cfg.email === "string" || cfg.email === null
|
|
65
|
+
? { email: cfg.email }
|
|
66
|
+
: {}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
31
69
|
export async function writeConfig(cfg) {
|
|
32
70
|
const targetPath = process.env.FLOOM_CONFIG_PATH ?? CONFIG_PATH;
|
|
33
71
|
const targetDir = dirname(targetPath);
|
package/dist/doctor.js
CHANGED
|
@@ -4,7 +4,7 @@ import { delimiter } from "node:path";
|
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { stat, readFile, access, readdir, constants, realpath } from "node:fs/promises";
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
|
-
import { readConfig, CONFIG_PATH, resolveApiUrl } from "./config.js";
|
|
7
|
+
import { readConfig, refreshConfigIfNeeded, CONFIG_PATH, resolveApiUrl } from "./config.js";
|
|
8
8
|
import { floomFetch } from "./lib/api.js";
|
|
9
9
|
import { c, symbols } from "./ui.js";
|
|
10
10
|
import { CLI_VERSION, compareSemverish, formatVersionLabel } from "./version.js";
|
|
@@ -33,6 +33,21 @@ async function checkAuth() {
|
|
|
33
33
|
checkOk: false,
|
|
34
34
|
});
|
|
35
35
|
if (res.status === 401) {
|
|
36
|
+
const refreshed = await refreshConfigIfNeeded(cfg, { force: true });
|
|
37
|
+
if (refreshed.accessToken !== cfg.accessToken) {
|
|
38
|
+
const retry = await floomFetch(`${apiUrl}/api/me`, "check authentication", {
|
|
39
|
+
token: refreshed.accessToken,
|
|
40
|
+
checkOk: false,
|
|
41
|
+
});
|
|
42
|
+
if (retry.ok) {
|
|
43
|
+
const data = (await retry.json());
|
|
44
|
+
return {
|
|
45
|
+
name: "Auth",
|
|
46
|
+
status: "ok",
|
|
47
|
+
detail: data.email ? `Signed in as ${data.email} (refreshed)` : "Signed in (refreshed)",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
36
51
|
return {
|
|
37
52
|
name: "Auth",
|
|
38
53
|
status: "fail",
|