@ipv9/tokentracker-cli 0.39.33 → 0.39.35
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/README.md +48 -5
- package/dashboard/dist/assets/{ActivityHeatmap-B8dR4C_0.js → ActivityHeatmap-rUm9bSZ9.js} +1 -1
- package/dashboard/dist/assets/{Card-UnYzwQJR.js → Card-YWr91b5b.js} +1 -1
- package/dashboard/dist/assets/DashboardPage-DdJOVJuw.js +19 -0
- package/dashboard/dist/assets/{DevicePage-CZFnVVjk.js → DevicePage-CQMG1bh8.js} +1 -1
- package/dashboard/dist/assets/{DialogTitle-BZl-I43S.js → DialogTitle-BM0Hz4Pq.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-0EQh6r0x.js → FadeIn-D8xysY3i.js} +1 -1
- package/dashboard/dist/assets/{InsforgeUserHeaderControls-BeA5yiNr.js → InsforgeUserHeaderControls-CsAafXyj.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-BkjSnzmW.js → IpCheckPage-Bbg9erkT.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-CCj37Lvh.js → LandingPage-BCMsWOwJ.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardAvatar-B4viOzHY.js → LeaderboardAvatar-CkQa4EX2.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-CQV2N36e.js → LeaderboardPage-CyDX3tDL.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfileModal-CNKo1dRR.js → LeaderboardProfileModal-CMctMA-p.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardProfilePage-FvRutqM5.js → LeaderboardProfilePage-DTZ_6dBt.js} +1 -1
- package/dashboard/dist/assets/LimitsPage-V7939U8b.js +2 -0
- package/dashboard/dist/assets/{LocalOnlyNotice-BH_BM61g.js → LocalOnlyNotice-dODOM3SB.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-BOs7Vxww.js → LoginPage-CE5GBEI2.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-Dd2SS-kl.js → PopoverPopup-CRzMMFsC.js} +1 -1
- package/dashboard/dist/assets/{Select-DKPyTgtq.js → Select-m6edgfye.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-JqKVOv-o.js → SelectItemText-DIoTPvZM.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-CJfhq1dP.js → SettingsPage-DObaSleW.js} +1 -1
- package/dashboard/dist/assets/{SkillsPage-C6tkEm2L.js → SkillsPage-BSi26dZo.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-CL32K7OS.js → WidgetsPage-CTl7OtvF.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-7AnZnCu_.js → WrappedPage-BXwhD9aq.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-2_t43gcm.js → arrow-up-right-DxdoYoxg.js} +1 -1
- package/dashboard/dist/assets/{download-INj0jPNk.js → download-BZkwGDg8.js} +1 -1
- package/dashboard/dist/assets/{info-D7mMY73X.js → info-DRaQWOpM.js} +1 -1
- package/dashboard/dist/assets/{main-D2nNo9eK.js → main-CuaPRwHu.js} +5 -2
- package/dashboard/dist/assets/main-DAcSUW2t.css +1 -0
- package/dashboard/dist/assets/use-limits-display-prefs-5cj2WfP-.js +1 -0
- package/dashboard/dist/assets/{use-native-settings-Dacr_YkP.js → use-native-settings-BfydbPtC.js} +1 -1
- package/dashboard/dist/assets/{use-spring-CE3dBlxJ.js → use-spring-BxDSGjR_.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-BOjNomCE.js → use-usage-limits-D_5PMCyF.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-V1KRKBNl.js → useCurrency-DQhzQX2k.js} +1 -1
- package/dashboard/dist/assets/{useOpenInteractionType-DVyniqcO.js → useOpenInteractionType--grUNSll.js} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dashboard/dist/share.html +2 -2
- package/package.json +1 -1
- package/src/cli.js +3 -3
- package/src/commands/doctor.js +5 -0
- package/src/commands/serve.js +3 -1
- package/src/lib/browser-auth.js +40 -13
- package/src/lib/doctor.js +104 -1
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/usage-limits.js +133 -1
- package/dashboard/dist/assets/DashboardPage-CB24v0ry.js +0 -19
- package/dashboard/dist/assets/LimitsPage-By5T54_9.js +0 -2
- package/dashboard/dist/assets/main-CGmdZkmj.css +0 -1
- package/dashboard/dist/assets/use-limits-display-prefs-CbW7JdJz.js +0 -1
package/src/commands/doctor.js
CHANGED
package/src/commands/serve.js
CHANGED
|
@@ -334,7 +334,7 @@ function parseArgs(argv, env = process.env) {
|
|
|
334
334
|
const opts = {
|
|
335
335
|
port: envPort || DEFAULT_PORT,
|
|
336
336
|
portExplicit: Boolean(envPort),
|
|
337
|
-
open:
|
|
337
|
+
open: false,
|
|
338
338
|
sync: false,
|
|
339
339
|
};
|
|
340
340
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -347,6 +347,8 @@ function parseArgs(argv, env = process.env) {
|
|
|
347
347
|
}
|
|
348
348
|
} else if (arg === "--no-open") {
|
|
349
349
|
opts.open = false;
|
|
350
|
+
} else if (arg === "--open") {
|
|
351
|
+
opts.open = true;
|
|
350
352
|
} else if (arg === "--sync") {
|
|
351
353
|
opts.sync = true;
|
|
352
354
|
} else if (arg === "--no-sync") {
|
package/src/lib/browser-auth.js
CHANGED
|
@@ -158,7 +158,40 @@ function buildBrowserList() {
|
|
|
158
158
|
return [def, ...all.filter((b) => b !== def)];
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
function
|
|
161
|
+
function buildBrowserOpenErrorMessage({ url, command, error, platform = process.platform } = {}) {
|
|
162
|
+
const commandName =
|
|
163
|
+
command || (platform === "win32" ? "cmd" : platform === "darwin" ? "open" : "xdg-open");
|
|
164
|
+
const reason =
|
|
165
|
+
error?.code === "ENOENT" ? `${commandName} not found` : error?.message || String(error || "unknown error");
|
|
166
|
+
const lines = [
|
|
167
|
+
`Could not open browser automatically: ${reason}.`,
|
|
168
|
+
`Open manually: ${url}`,
|
|
169
|
+
];
|
|
170
|
+
if (platform === "linux" && commandName === "xdg-open") {
|
|
171
|
+
lines.push("Linux fix: sudo apt install -y xdg-utils");
|
|
172
|
+
}
|
|
173
|
+
return `${lines.join("\n")}\n`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function spawnBrowserCommand(
|
|
177
|
+
command,
|
|
178
|
+
args,
|
|
179
|
+
{ url, platform = process.platform, stderr = process.stderr, spawn = cp.spawn } = {},
|
|
180
|
+
) {
|
|
181
|
+
try {
|
|
182
|
+
const child = spawn(command, args, { stdio: "ignore", detached: true });
|
|
183
|
+
child.on("error", (error) => {
|
|
184
|
+
stderr.write(buildBrowserOpenErrorMessage({ url, command, error, platform }));
|
|
185
|
+
});
|
|
186
|
+
child.unref();
|
|
187
|
+
return child;
|
|
188
|
+
} catch (error) {
|
|
189
|
+
stderr.write(buildBrowserOpenErrorMessage({ url, command, error, platform }));
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function openInBrowser(url, { stderr = process.stderr } = {}) {
|
|
162
195
|
const platform = process.platform;
|
|
163
196
|
|
|
164
197
|
if (platform === "darwin") {
|
|
@@ -230,15 +263,10 @@ else
|
|
|
230
263
|
open location "${url}"
|
|
231
264
|
end if
|
|
232
265
|
`;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
child.unref();
|
|
236
|
-
} catch (_e) {
|
|
266
|
+
const child = spawnBrowserCommand("osascript", ["-e", script], { url, platform, stderr });
|
|
267
|
+
if (!child) {
|
|
237
268
|
// Fallback to plain open
|
|
238
|
-
|
|
239
|
-
const child = cp.spawn("open", [url], { stdio: "ignore", detached: true });
|
|
240
|
-
child.unref();
|
|
241
|
-
} catch (_e2) {}
|
|
269
|
+
spawnBrowserCommand("open", [url], { url, platform, stderr });
|
|
242
270
|
}
|
|
243
271
|
return;
|
|
244
272
|
}
|
|
@@ -254,10 +282,7 @@ end if
|
|
|
254
282
|
args = [url];
|
|
255
283
|
}
|
|
256
284
|
|
|
257
|
-
|
|
258
|
-
const child = cp.spawn(cmd, args, { stdio: "ignore", detached: true });
|
|
259
|
-
child.unref();
|
|
260
|
-
} catch (_e) {}
|
|
285
|
+
spawnBrowserCommand(cmd, args, { url, platform, stderr });
|
|
261
286
|
}
|
|
262
287
|
|
|
263
288
|
function resolvePostAuthRedirect({ dashboardUrl, authUrl }) {
|
|
@@ -278,4 +303,6 @@ function resolvePostAuthRedirect({ dashboardUrl, authUrl }) {
|
|
|
278
303
|
module.exports = {
|
|
279
304
|
beginBrowserAuth,
|
|
280
305
|
openInBrowser,
|
|
306
|
+
buildBrowserOpenErrorMessage,
|
|
307
|
+
spawnBrowserCommand,
|
|
281
308
|
};
|
package/src/lib/doctor.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const fs = require("node:fs/promises");
|
|
2
2
|
const { constants } = require("node:fs");
|
|
3
|
+
const path = require("node:path");
|
|
3
4
|
|
|
4
5
|
const { readJsonStrict } = require("./fs");
|
|
5
6
|
|
|
@@ -9,10 +10,14 @@ async function buildDoctorReport({
|
|
|
9
10
|
fetch = globalThis.fetch,
|
|
10
11
|
now = () => new Date(),
|
|
11
12
|
paths = {},
|
|
13
|
+
system = null,
|
|
12
14
|
} = {}) {
|
|
13
15
|
const checks = [];
|
|
14
16
|
|
|
15
17
|
checks.push(...buildRuntimeChecks(runtime));
|
|
18
|
+
if (system) {
|
|
19
|
+
checks.push(...(await buildSystemChecks(system)));
|
|
20
|
+
}
|
|
16
21
|
|
|
17
22
|
if (paths.trackerDir) {
|
|
18
23
|
checks.push(await checkTrackerDir(paths.trackerDir));
|
|
@@ -42,6 +47,99 @@ async function buildDoctorReport({
|
|
|
42
47
|
};
|
|
43
48
|
}
|
|
44
49
|
|
|
50
|
+
async function buildSystemChecks({
|
|
51
|
+
nodeVersion = process.version,
|
|
52
|
+
platform = process.platform,
|
|
53
|
+
env = process.env,
|
|
54
|
+
commandExists = commandExistsOnPath,
|
|
55
|
+
} = {}) {
|
|
56
|
+
return [
|
|
57
|
+
buildNodeVersionCheck(nodeVersion),
|
|
58
|
+
await buildBrowserOpenerCheck({ platform, env, commandExists }),
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function buildNodeVersionCheck(nodeVersion) {
|
|
63
|
+
const major = parseNodeMajor(nodeVersion);
|
|
64
|
+
const ok = Number.isFinite(major) && major >= 20;
|
|
65
|
+
return {
|
|
66
|
+
id: "runtime.node_version",
|
|
67
|
+
status: ok ? "ok" : "fail",
|
|
68
|
+
detail: ok ? `Node.js ${nodeVersion} satisfies >=20` : `Node.js ${nodeVersion || "unknown"} is below required >=20`,
|
|
69
|
+
critical: !ok,
|
|
70
|
+
meta: {
|
|
71
|
+
node_version: nodeVersion || null,
|
|
72
|
+
required_major: 20,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function buildBrowserOpenerCheck({ platform = process.platform, env = process.env, commandExists }) {
|
|
78
|
+
const headless = isHeadlessEnvironment({ platform, env });
|
|
79
|
+
if (headless) {
|
|
80
|
+
return {
|
|
81
|
+
id: "browser.opener",
|
|
82
|
+
status: "warn",
|
|
83
|
+
detail: "headless/session environment detected; use --no-open or open the printed URL manually",
|
|
84
|
+
critical: false,
|
|
85
|
+
meta: { platform, command: null, headless: true },
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (platform === "win32") {
|
|
90
|
+
return {
|
|
91
|
+
id: "browser.opener",
|
|
92
|
+
status: "ok",
|
|
93
|
+
detail: "Windows browser opener uses cmd /c start",
|
|
94
|
+
critical: false,
|
|
95
|
+
meta: { platform, command: "cmd", headless: false },
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const command = platform === "darwin" ? "open" : "xdg-open";
|
|
100
|
+
const exists = await commandExists(command, env);
|
|
101
|
+
return {
|
|
102
|
+
id: "browser.opener",
|
|
103
|
+
status: exists ? "ok" : "warn",
|
|
104
|
+
detail: exists
|
|
105
|
+
? `${command} available`
|
|
106
|
+
: command === "xdg-open"
|
|
107
|
+
? "xdg-open missing; install xdg-utils or use --no-open"
|
|
108
|
+
: `${command} missing; use --no-open`,
|
|
109
|
+
critical: false,
|
|
110
|
+
meta: {
|
|
111
|
+
platform,
|
|
112
|
+
command,
|
|
113
|
+
headless: false,
|
|
114
|
+
linux_fix: command === "xdg-open" && !exists ? "sudo apt install -y xdg-utils" : null,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function parseNodeMajor(nodeVersion) {
|
|
120
|
+
const match = String(nodeVersion || "").match(/^v?(\d+)/);
|
|
121
|
+
return match ? Number(match[1]) : NaN;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function isHeadlessEnvironment({ platform, env = {} } = {}) {
|
|
125
|
+
if (env.CI === "true" || env.HEADLESS === "true" || env.TOKENTRACKER_HEADLESS === "1") return true;
|
|
126
|
+
if (platform === "linux" && !env.DISPLAY && !env.WAYLAND_DISPLAY && !env.WSL_DISTRO_NAME) return true;
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function commandExistsOnPath(command, env = process.env) {
|
|
131
|
+
const pathValue = env.PATH || "";
|
|
132
|
+
const dirs = pathValue.split(path.delimiter).filter(Boolean);
|
|
133
|
+
for (const dir of dirs) {
|
|
134
|
+
const candidate = path.join(dir, command);
|
|
135
|
+
try {
|
|
136
|
+
await fs.access(candidate, constants.X_OK);
|
|
137
|
+
return true;
|
|
138
|
+
} catch (_e) {}
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
|
|
45
143
|
function buildRuntimeChecks(runtime = {}) {
|
|
46
144
|
const checks = [];
|
|
47
145
|
const baseUrl =
|
|
@@ -335,4 +433,9 @@ function summarizeChecks(checks = []) {
|
|
|
335
433
|
return summary;
|
|
336
434
|
}
|
|
337
435
|
|
|
338
|
-
module.exports = {
|
|
436
|
+
module.exports = {
|
|
437
|
+
buildDoctorReport,
|
|
438
|
+
buildBrowserOpenerCheck,
|
|
439
|
+
buildNodeVersionCheck,
|
|
440
|
+
isHeadlessEnvironment,
|
|
441
|
+
};
|