From edbd29473c18075d3d9dcd0b2a1967ebadcefbc2 Mon Sep 17 00:00:00 2001 From: janniks Date: Mon, 18 Nov 2024 19:21:30 +0100 Subject: [PATCH 1/3] fix: Update fetch input types to account for Request object as first fetch parameter --- packages/common/src/fetch.ts | 72 ++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/packages/common/src/fetch.ts b/packages/common/src/fetch.ts index 8fc206232..3ec7d07de 100644 --- a/packages/common/src/fetch.ts +++ b/packages/common/src/fetch.ts @@ -37,7 +37,10 @@ export const setFetchOptions = (ops: RequestInit): RequestInit => { }; /** @ignore */ -export async function fetchWrapper(input: RequestInfo, init?: RequestInit): Promise { +export async function fetchWrapper( + input: RequestInfo | URL, + init?: RequestInit +): Promise { const fetchOpts = {}; // Use the provided options in request options along with default or user provided values Object.assign(fetchOpts, defaultFetchOpts, init); @@ -46,11 +49,11 @@ export async function fetchWrapper(input: RequestInfo, init?: RequestInit): Prom return fetchResult; } -export type FetchFn = (url: string, init?: RequestInit) => Promise; +export type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise; /** * @ignore Internally used for letting networking functions specify "API" options. - * Should be compatible with the `client`s created by the API and RPC packages. + * Should be compatible with the `client`s created by the API and RPC client packages. */ export interface ClientOpts { baseUrl?: string; @@ -65,24 +68,41 @@ export interface ClientParam { export interface RequestContext { fetch: FetchFn; + + /** @deprecated This may in some cases be a Request/RequestInfo object instead of a string. For safety use `.input` instead. */ url: string; + + input: RequestInfo | URL; init: RequestInit; } export interface ResponseContext { fetch: FetchFn; + + /** @deprecated This may in some cases be a Request/RequestInfo object instead of a string. For safety use `.input` instead. */ url: string; + + input: RequestInfo | URL; init: RequestInit; + response: Response; } +/** @deprecated Use {@link FetchArgs} instead. The `.url` property is may also be a Request object. */ export interface FetchParams { url: string; init: RequestInit; } +export interface FetchArgs { + input: RequestInfo | URL; + init?: RequestInit; +} + export interface FetchMiddleware { - pre?: (context: RequestContext) => PromiseLike | FetchParams | void; + pre?: ( + context: RequestContext + ) => PromiseLike | FetchParams | FetchArgs | void; post?: (context: ResponseContext) => Promise | Response | void; } export interface ApiKeyMiddlewareOpts { @@ -130,16 +150,16 @@ export function createApiKeyMiddleware({ }; } -function argsForCreateFetchFn(args: any[]): { fetchLib: FetchFn; middlewares: FetchMiddleware[] } { - let fetchLib: FetchFn = fetchWrapper; - let middlewares: FetchMiddleware[] = []; - if (args.length > 0 && typeof args[0] === 'function') { - fetchLib = args.shift(); +/** @internal */ +function argsForCreateFetchFn(args: any[]): { fetch: FetchFn; middlewares: FetchMiddleware[] } { + if (typeof args[0] === 'function') { + return { + fetch: args.shift(), // first arg is fetch function + middlewares: args, + }; } - if (args.length > 0) { - middlewares = args; // remaining args - } - return { fetchLib, middlewares }; + + return { fetch: fetchWrapper, middlewares: args }; } /** @@ -152,35 +172,39 @@ function argsForCreateFetchFn(args: any[]): { fetchLib: FetchFn; middlewares: Fe * ``` * @category Network */ -export function createFetchFn(fetchLib: FetchFn, ...middleware: FetchMiddleware[]): FetchFn; +export function createFetchFn(fetchFn: FetchFn, ...middleware: FetchMiddleware[]): FetchFn; export function createFetchFn(...middleware: FetchMiddleware[]): FetchFn; export function createFetchFn(...args: any[]): FetchFn { - const { fetchLib, middlewares } = argsForCreateFetchFn(args); + const { fetch, middlewares } = argsForCreateFetchFn(args); - const fetchFn = async (url: string, init?: RequestInit | undefined): Promise => { - let fetchParams = { url, init: init ?? {} }; + const fetchFn: FetchFn = async (input, init) => { + let fetchParams: FetchArgs = { input, init: init ?? {} }; for (const middleware of middlewares) { if (typeof middleware.pre === 'function') { const result = await Promise.resolve( middleware.pre({ - fetch: fetchLib, - ...fetchParams, + fetch, + url: fetchParams.input as string, // @deprecated (type mismatch, but this is backwards compatible behavior) + input: fetchParams.input, + init: fetchParams.init ?? {}, }) ); - fetchParams = result ?? fetchParams; + if (result && 'url' in result) (result as unknown as FetchArgs).input = result.url; + fetchParams = (result as FetchArgs | void) ?? fetchParams; } } - let response = await fetchLib(fetchParams.url, fetchParams.init); + let response = await fetch(fetchParams.input, fetchParams.init); for (const middleware of middlewares) { if (typeof middleware.post === 'function') { const result = await Promise.resolve( middleware.post({ - fetch: fetchLib, - url: fetchParams.url, - init: fetchParams.init, + fetch, + url: fetchParams.input as string, // @deprecated (type mismatch, but this is backwards compatible behavior) + input: fetchParams.input, + init: fetchParams.init ?? {}, response: response?.clone() ?? response, }) ); From 64885fcf6874a47b9437f9e48bd73257fbd4c8f4 Mon Sep 17 00:00:00 2001 From: janniks Date: Tue, 19 Nov 2024 13:10:57 +0100 Subject: [PATCH 2/3] fix: Fix createApiKeyMiddleware function to account for non-string input parameters --- packages/common/src/fetch.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/common/src/fetch.ts b/packages/common/src/fetch.ts index 3ec7d07de..310862e94 100644 --- a/packages/common/src/fetch.ts +++ b/packages/common/src/fetch.ts @@ -1,4 +1,7 @@ +import { isInstance } from './utils'; + // Define default request options and allow modification using getters, setters + // Reference: https://developer.mozilla.org/en-US/docs/Web/API/Request/Request const defaultFetchOpts: RequestInit = { // By default referrer value will be client:origin: above reference link @@ -138,8 +141,13 @@ export function createApiKeyMiddleware({ }: ApiKeyMiddlewareOpts): FetchMiddleware { return { pre: context => { - const reqUrl = new URL(context.url); - if (!hostMatches(reqUrl.host, host)) return; // Skip middleware if host does not match pattern + const url = isInstance(context.input, URL) + ? context.input + : typeof context.input === 'string' + ? new URL(context.input) + : new URL(context.input.url); + + if (!hostMatches(url.host, host)) return; // Skip middleware if host does not match pattern const headers = context.init.headers instanceof Headers From 64a49b589b2542db8e4ed79848a93cbffc8ba13d Mon Sep 17 00:00:00 2001 From: janniks Date: Tue, 19 Nov 2024 13:19:50 +0100 Subject: [PATCH 3/3] ci: trigger