Skip to content

Commit b591f46

Browse files
authored
feat(core): top-level whenClientChanged API (#1164)
1 parent 7bb63d7 commit b591f46

5 files changed

Lines changed: 66 additions & 0 deletions

File tree

.changeset/fresh-boxes-enjoy.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@reactive-dot/core": minor
3+
---
4+
5+
Added top-level `whenClientChanged` API.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { getClient as baseGetClient } from "../actions/get-client.js";
2+
import { defineConfig } from "../config.js";
3+
import { whenClientChanged } from "./when-client-changed.js";
4+
import { firstValueFrom } from "rxjs";
5+
import { afterEach, expect, it, vi } from "vitest";
6+
7+
vi.mock("../actions/get-client.js");
8+
9+
const config = defineConfig({
10+
chains: { test: { descriptor: {}, provider: {} } as never },
11+
});
12+
13+
afterEach(() => {
14+
vi.clearAllMocks();
15+
});
16+
17+
it("defers getClient until subscribing", async () => {
18+
const mockClient = { id: "test-client" };
19+
vi.mocked(baseGetClient).mockResolvedValue(mockClient as never);
20+
21+
const observable = whenClientChanged(config, { chainId: "test" });
22+
expect(baseGetClient).not.toHaveBeenCalled();
23+
24+
const result = await firstValueFrom(observable);
25+
expect(baseGetClient).toHaveBeenCalledTimes(1);
26+
expect(result).toEqual(mockClient);
27+
});
28+
29+
it("re-invokes getClient for each subscription", async () => {
30+
const mockClient = { id: "test-client" };
31+
vi.mocked(baseGetClient).mockResolvedValue(mockClient as never);
32+
33+
const observable = whenClientChanged(config, { chainId: "test" });
34+
35+
const promise1 = firstValueFrom(observable);
36+
const promise2 = firstValueFrom(observable);
37+
38+
await Promise.all([promise1, promise2]);
39+
40+
expect(baseGetClient).toHaveBeenCalledTimes(2);
41+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { InferChainId } from "../chains.js";
2+
import type { Config } from "../config.js";
3+
import { getClient } from "./get-client.js";
4+
import { defer } from "rxjs";
5+
6+
/**
7+
* Subscribe to client changes.
8+
*
9+
* @param config - The configuration
10+
* @param options - Additional options
11+
* @returns The currently configured client observable
12+
*/
13+
export function whenClientChanged<TConfig extends Config>(
14+
config: TConfig,
15+
options: { chainId: InferChainId<TConfig> },
16+
) {
17+
return defer(() => getClient(config, options));
18+
}

packages/core/src/index.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ it("should match inline snapshot", () =>
55
expect(Object.keys(exports)).toMatchInlineSnapshot(`
66
[
77
"whenAccountsChanged",
8+
"whenClientChanged",
89
"whenConnectedWalletsChanged",
910
"whenWalletsChanged",
1011
"defineConfig",

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export type { Address } from "./address.js";
22
export { whenAccountsChanged } from "./apis/when-accounts-changed.js";
3+
export { whenClientChanged } from "./apis/when-client-changed.js";
34
export { whenConnectedWalletsChanged } from "./apis/when-connected-wallets-changed.js";
45
export { whenWalletsChanged } from "./apis/when-wallets-changed.js";
56
export type { AsyncValue } from "./async-state.js";

0 commit comments

Comments
 (0)