mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-30 10:18:25 -05:00
fix(client): prevent duplicate signal processing in atom listeners (#7018)
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createDynamicPathProxy } from "./proxy";
|
||||
|
||||
describe("createDynamicPathProxy", () => {
|
||||
it("should avoid duplicate signal processing", async () => {
|
||||
const client = vi.fn(async (path, options) => {
|
||||
if (options?.onSuccess) {
|
||||
await options.onSuccess({} as any);
|
||||
}
|
||||
return {
|
||||
data: {},
|
||||
error: null,
|
||||
};
|
||||
});
|
||||
const knownPathMethods = {
|
||||
"/test": "POST",
|
||||
} as const;
|
||||
|
||||
const signalSet = vi.fn();
|
||||
const signalGet = vi.fn(() => false);
|
||||
|
||||
const atoms = {
|
||||
testSignal: {
|
||||
get: signalGet,
|
||||
set: signalSet,
|
||||
subscribe: () => () => {},
|
||||
listen: () => () => {},
|
||||
off: () => {},
|
||||
value: false,
|
||||
} as any,
|
||||
};
|
||||
const atomListeners = [
|
||||
{
|
||||
matcher: (path: string) => path === "/test",
|
||||
signal: "testSignal",
|
||||
},
|
||||
{
|
||||
matcher: (path: string) => path === "/test",
|
||||
signal: "testSignal",
|
||||
},
|
||||
];
|
||||
|
||||
const proxy = createDynamicPathProxy(
|
||||
{
|
||||
test: {},
|
||||
},
|
||||
client as any,
|
||||
knownPathMethods,
|
||||
atoms,
|
||||
atomListeners,
|
||||
);
|
||||
|
||||
vi.useFakeTimers();
|
||||
|
||||
await (proxy.test as any)();
|
||||
|
||||
expect(client).toHaveBeenCalled();
|
||||
|
||||
vi.runAllTimers();
|
||||
|
||||
expect(signalSet).toHaveBeenCalledTimes(1);
|
||||
|
||||
vi.useRealTimers();
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import type {
|
||||
BetterAuthClientPlugin,
|
||||
ClientAtomListener,
|
||||
ClientFetchOption,
|
||||
} from "@better-auth/core";
|
||||
import type { BetterFetch } from "@better-fetch/fetch";
|
||||
@@ -100,9 +101,15 @@ export function createDynamicPathProxy<T extends Record<string, any>>(
|
||||
*/
|
||||
const matches = atomListeners.filter((s) => s.matcher(routePath));
|
||||
if (!matches.length) return;
|
||||
|
||||
const visited = new Set<ClientAtomListener["signal"]>();
|
||||
for (const match of matches) {
|
||||
const signal = atoms[match.signal as any];
|
||||
if (!signal) return;
|
||||
if (visited.has(match.signal)) {
|
||||
continue;
|
||||
}
|
||||
visited.add(match.signal);
|
||||
/**
|
||||
* To avoid race conditions we set the signal in a setTimeout
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user