Skip to content

Commit cd1cf2d

Browse files
committed
fix(rest-api-sdk): preserve middleware instances in app-scoped client
1 parent de3e0fa commit cd1cf2d

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

packages/rest-api-sdk/src/api.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,17 @@ export class Api extends DefaultApi {
9595
}
9696
}
9797

98+
function isPlainObject(
99+
value: unknown,
100+
): value is Record<string, unknown> | Record<string, never> {
101+
if (!value || typeof value !== "object" || Array.isArray(value)) {
102+
return false;
103+
}
104+
105+
const prototype = Object.getPrototypeOf(value);
106+
return prototype === Object.prototype || prototype === null;
107+
}
108+
98109
function scopeApiToAppId<T extends object>(
99110
api: T,
100111
appId: string,
@@ -118,9 +129,11 @@ function scopeApiToAppId<T extends object>(
118129
};
119130

120131
return (arg1: unknown, ...rest: unknown[]) => {
121-
if (arg1 && typeof arg1 === "object" && !Array.isArray(arg1)) {
132+
const isWithMethod =
133+
typeof prop === "string" && prop.startsWith("with");
134+
if (!isWithMethod && isPlainObject(arg1)) {
122135
const args =
123-
"appId" in (arg1 as object) ? arg1 : { ...(arg1 as object), appId };
136+
"appId" in arg1 ? arg1 : { ...arg1, appId };
124137
const result = (value as (...args: unknown[]) => unknown).call(
125138
target,
126139
args,

packages/rest-api-sdk/test/createAppClient.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,36 @@ describe("createAppClient", () => {
7171
"https://example.test/apps/app-123/flags",
7272
);
7373
});
74+
75+
it("preserves class-based middleware hooks after withMiddleware", async () => {
76+
const fetchApi = vi.fn(
77+
async (_input: RequestInfo | URL, _init?: RequestInit) =>
78+
new Response(JSON.stringify(listFlagsResponse), {
79+
status: 200,
80+
headers: { "Content-Type": "application/json" },
81+
}),
82+
);
83+
const client = createAppClient("app-123", {
84+
basePath: "https://example.test",
85+
fetchApi,
86+
});
87+
88+
class PrototypePreMiddleware implements Middleware {
89+
preCalls = 0;
90+
91+
async pre({ url, init }: { url: string; init: RequestInit }) {
92+
this.preCalls += 1;
93+
return { url, init };
94+
}
95+
}
96+
97+
const middleware = new PrototypePreMiddleware();
98+
const withMiddleware = client.withMiddleware(middleware);
99+
100+
await expect(
101+
(withMiddleware as unknown as ScopedListFlagsClient).listFlags({}),
102+
).resolves.toEqual(listFlagsResponse);
103+
expect(middleware.preCalls).toBe(1);
104+
expect(fetchApi).toHaveBeenCalledTimes(1);
105+
});
74106
});

0 commit comments

Comments
 (0)