Skip to content

Commit 94e3b16

Browse files
authored
Merge branch 'main' into chris/auth-improvements
2 parents 901da5c + 26b0961 commit 94e3b16

7 files changed

Lines changed: 102 additions & 17 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@alchemy/cli",
3-
"version": "0.5.0",
3+
"version": "0.5.1",
44
"description": "Alchemy CLI — interact with blockchain data",
55
"type": "module",
66
"bin": {

scripts/postinstall.cjs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#!/usr/bin/env node
22

3+
const { unlinkSync } = require("node:fs");
4+
const { join } = require("node:path");
5+
36
function isGlobalInstall() {
47
return process.env.npm_config_global === "true";
58
}
@@ -8,8 +11,21 @@ function isCI() {
811
return process.env.CI === "true";
912
}
1013

14+
function clearUpdateCache() {
15+
const home = process.env.HOME || require("node:os").homedir();
16+
const configHome = process.env.XDG_CONFIG_HOME || join(home, ".config");
17+
const cachePath = process.env.ALCHEMY_CONFIG
18+
? process.env.ALCHEMY_CONFIG.replace(/config\.json$/, ".update-check")
19+
: join(configHome, "alchemy", ".update-check");
20+
try {
21+
unlinkSync(cachePath);
22+
} catch {
23+
// Cache file may not exist yet — that's fine.
24+
}
25+
}
26+
1127
if (isGlobalInstall() && !isCI()) {
12-
// Keep this concise so it stays readable in npm install output.
28+
clearUpdateCache();
1329
console.log("");
1430
console.log("◆ Alchemy CLI installed");
1531
console.log(" Run `alchemy` to get started.");

src/lib/update-check.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { esc } from "./colors.js";
77
declare const __CLI_VERSION__: string;
88

99
const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
10-
const UPDATE_INSTALL_COMMAND = "npm i -g @alchemy/cli";
10+
const UPDATE_INSTALL_COMMAND = "npm i -g @alchemy/cli@latest";
1111

1212
interface UpdateCache {
1313
latest: string;

tests/commands/onboarding.test.ts

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ describe("onboarding flow", () => {
1313
getLoginUrl: vi.fn().mockReturnValue("https://auth.alchemy.com/login"),
1414
}));
1515
vi.doMock("../../src/lib/update-check.js", () => ({
16-
getUpdateNoticeLines: vi.fn().mockReturnValue([]),
16+
getUpdateNoticeLines: vi.fn().mockReturnValue([
17+
" Update available 0.2.0 -> 9.9.9",
18+
" Run npm i -g @alchemy/cli@latest to update",
19+
]),
1720
}));
1821
vi.doMock("../../src/lib/config.js", () => ({
1922
load: vi.fn().mockReturnValue({}),
@@ -44,16 +47,82 @@ describe("onboarding flow", () => {
4447
}),
4548
AUTH_PORT: 16424,
4649
getLoginUrl: vi.fn().mockReturnValue("https://auth.alchemy.com/login"),
50+
vi.doMock("../../src/lib/terminal-ui.js", () => ({
51+
promptSelect: vi.fn().mockResolvedValue("api-key"),
52+
promptText: vi.fn().mockResolvedValue("api_test"),
53+
}));
54+
vi.doMock("../../src/lib/update-check.js", () => ({
55+
getUpdateNoticeLines: vi.fn().mockReturnValue([
56+
" Update available 0.2.0 -> 9.9.9",
57+
" Run npm i -g @alchemy/cli@latest to update",
58+
]),
59+
}));
60+
vi.doMock("../../src/lib/config.js", () => ({
61+
load,
62+
save,
63+
}));
64+
vi.doMock("../../src/lib/ui.js", () => ({
65+
brand: (s: string) => s,
66+
bold: (s: string) => s,
67+
brandedHelp: () => "",
68+
dim: (s: string) => s,
69+
green: (s: string) => s,
70+
maskIf: (s: string) => s,
71+
printKeyValueBox: vi.fn(),
4772
}));
4873
vi.doMock("../../src/commands/auth.js", () => ({
4974
selectAppAfterAuth: vi.fn(),
5075
}));
5176
vi.doMock("../../src/lib/update-check.js", () => ({
52-
getUpdateNoticeLines: vi.fn().mockReturnValue([]),
77+
getUpdateNoticeLines: vi.fn().mockReturnValue([
78+
" Update available 0.2.0 -> 9.9.9",
79+
" Run npm i -g @alchemy/cli@latest to update",
80+
]),
5381
}));
5482
vi.doMock("../../src/lib/config.js", () => ({
5583
load: vi.fn().mockReturnValue({}),
56-
save,
84+
save: vi.fn(),
85+
}));
86+
vi.doMock("../../src/lib/ui.js", () => ({
87+
brand: (s: string) => s,
88+
bold: (s: string) => s,
89+
brandedHelp: () => "",
90+
dim: (s: string) => s,
91+
green: (s: string) => s,
92+
maskIf: (s: string) => s,
93+
printKeyValueBox: vi.fn(),
94+
}));
95+
vi.doMock("../../src/lib/admin-client.js", () => ({
96+
AdminClient: vi.fn(),
97+
}));
98+
vi.doMock("../../src/commands/config.js", () => ({
99+
selectOrCreateApp: vi.fn(),
100+
}));
101+
vi.doMock("../../src/commands/wallet.js", () => ({
102+
generateAndPersistWallet: vi.fn(),
103+
importAndPersistWallet: vi.fn(),
104+
}));
105+
106+
const { runOnboarding } = await import("../../src/commands/onboarding.js");
107+
const completed = await runOnboarding({} as never);
108+
expect(completed).toBe(false);
109+
});
110+
111+
it("prints next steps when selected path remains incomplete", async () => {
112+
const logSpy = vi.spyOn(console, "log").mockImplementation(() => {});
113+
vi.doMock("../../src/lib/terminal-ui.js", () => ({
114+
promptSelect: vi.fn().mockResolvedValue("api-key"),
115+
promptText: vi.fn().mockResolvedValue(""),
116+
}));
117+
vi.doMock("../../src/lib/update-check.js", () => ({
118+
getUpdateNoticeLines: vi.fn().mockReturnValue([
119+
" Update available 0.2.0 -> 9.9.9",
120+
" Run npm i -g @alchemy/cli@latest to update",
121+
]),
122+
}));
123+
vi.doMock("../../src/lib/config.js", () => ({
124+
load: vi.fn().mockReturnValue({}),
125+
save: vi.fn(),
57126
}));
58127
vi.doMock("../../src/lib/ui.js", () => ({
59128
brand: (s: string) => s,
@@ -85,7 +154,7 @@ describe("onboarding flow", () => {
85154
vi.doMock("../../src/lib/update-check.js", () => ({
86155
getUpdateNoticeLines: vi.fn().mockReturnValue([
87156
" Update available 0.2.0 -> 9.9.9",
88-
" Run npm i -g @alchemy/cli to update",
157+
" Run npm i -g @alchemy/cli@latest to update",
89158
]),
90159
}));
91160
vi.doMock("../../src/lib/config.js", () => ({
@@ -105,6 +174,6 @@ describe("onboarding flow", () => {
105174
const { runOnboarding } = await import("../../src/commands/onboarding.js");
106175
await runOnboarding({} as never, "9.9.9");
107176
expect(logSpy).toHaveBeenCalledWith(" Update available 0.2.0 -> 9.9.9");
108-
expect(logSpy).toHaveBeenCalledWith(" Run npm i -g @alchemy/cli to update");
177+
expect(logSpy).toHaveBeenCalledWith(" Run npm i -g @alchemy/cli@latest to update");
109178
});
110179
});

tests/commands/update-check.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ describe("update-check command", () => {
2222
currentVersion: "0.2.0",
2323
latestVersion: "0.3.0",
2424
updateAvailable: true,
25-
installCommand: "npm i -g @alchemy/cli",
25+
installCommand: "npm i -g @alchemy/cli@latest",
2626
checkedAt: 1_700_000_000_000,
2727
}),
2828
}));
@@ -39,7 +39,7 @@ describe("update-check command", () => {
3939
currentVersion: "0.2.0",
4040
latestVersion: "0.3.0",
4141
updateAvailable: true,
42-
installCommand: "npm i -g @alchemy/cli",
42+
installCommand: "npm i -g @alchemy/cli@latest",
4343
checkedAt: 1_700_000_000_000,
4444
});
4545
});
@@ -59,7 +59,7 @@ describe("update-check command", () => {
5959
currentVersion: "0.2.0",
6060
latestVersion: "0.3.0",
6161
updateAvailable: true,
62-
installCommand: "npm i -g @alchemy/cli",
62+
installCommand: "npm i -g @alchemy/cli@latest",
6363
checkedAt: 1_700_000_000_000,
6464
}),
6565
}));
@@ -77,7 +77,7 @@ describe("update-check command", () => {
7777
["Latest version", "0.3.0"],
7878
["Update available", "yes"],
7979
["Checked at", "2023-11-14T22:13:20.000Z"],
80-
["Install", "npm i -g @alchemy/cli"],
80+
["Install", "npm i -g @alchemy/cli@latest"],
8181
]);
8282
});
8383
});

tests/e2e/cli.e2e.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ describe("CLI mock E2E", () => {
417417
currentVersion: "0.2.0",
418418
latestVersion: "9.9.9",
419419
updateAvailable: true,
420-
installCommand: "npm i -g @alchemy/cli",
420+
installCommand: "npm i -g @alchemy/cli@latest",
421421
checkedAt,
422422
});
423423
});

tests/lib/update-check.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ describe("getUpdateStatus", () => {
111111
currentVersion: "0.0.0",
112112
latestVersion: "9.9.9",
113113
updateAvailable: true,
114-
installCommand: "npm i -g @alchemy/cli",
114+
installCommand: "npm i -g @alchemy/cli@latest",
115115
checkedAt,
116116
});
117117
expect(execFileSync).not.toHaveBeenCalled();
@@ -132,7 +132,7 @@ describe("getUpdateStatus", () => {
132132
currentVersion: "0.0.0",
133133
latestVersion: "9.9.9",
134134
updateAvailable: true,
135-
installCommand: "npm i -g @alchemy/cli",
135+
installCommand: "npm i -g @alchemy/cli@latest",
136136
checkedAt,
137137
});
138138
});
@@ -151,7 +151,7 @@ describe("getUpdateStatus", () => {
151151
currentVersion: "0.0.0",
152152
latestVersion: null,
153153
updateAvailable: false,
154-
installCommand: "npm i -g @alchemy/cli",
154+
installCommand: "npm i -g @alchemy/cli@latest",
155155
checkedAt: null,
156156
});
157157
});
@@ -167,7 +167,7 @@ describe("printUpdateNotice", () => {
167167
const output = writeSpy.mock.calls[0][0] as string;
168168
expect(output).toContain("Update available");
169169
expect(output).toContain("1.0.0");
170-
expect(output).toContain("npm i -g @alchemy/cli");
170+
expect(output).toContain("npm i -g @alchemy/cli@latest");
171171

172172
writeSpy.mockRestore();
173173
});

0 commit comments

Comments
 (0)