run prettier (#995)
This commit is contained in:
parent
968b951795
commit
1150b1d843
1 changed files with 32176 additions and 33684 deletions
|
|
@ -1,10 +1,5 @@
|
|||
import {
|
||||
auth,
|
||||
extractResourceMetadataUrl,
|
||||
OAuthClientProvider,
|
||||
UnauthorizedError,
|
||||
} from "./auth.js";
|
||||
import { FetchLike } from "../shared/transport.js";
|
||||
import { auth, extractResourceMetadataUrl, OAuthClientProvider, UnauthorizedError } from './auth.js';
|
||||
import { FetchLike } from '../shared/transport.js';
|
||||
|
||||
/**
|
||||
* Middleware function that wraps and enhances fetch functionality.
|
||||
|
|
@ -39,114 +34,106 @@ export type Middleware = (next: FetchLike) => FetchLike;
|
|||
* @returns A fetch middleware function
|
||||
*/
|
||||
export const withOAuth =
|
||||
(provider: OAuthClientProvider, baseUrl?: string | URL): Middleware =>
|
||||
(next) => {
|
||||
return async (input, init) => {
|
||||
const makeRequest = async (): Promise<Response> => {
|
||||
const headers = new Headers(init?.headers);
|
||||
(provider: OAuthClientProvider, baseUrl?: string | URL): Middleware =>
|
||||
next => {
|
||||
return async (input, init) => {
|
||||
const makeRequest = async (): Promise<Response> => {
|
||||
const headers = new Headers(init?.headers);
|
||||
|
||||
// Add authorization header if tokens are available
|
||||
const tokens = await provider.tokens();
|
||||
if (tokens) {
|
||||
headers.set("Authorization", `Bearer ${tokens.access_token}`);
|
||||
}
|
||||
// Add authorization header if tokens are available
|
||||
const tokens = await provider.tokens();
|
||||
if (tokens) {
|
||||
headers.set('Authorization', `Bearer ${tokens.access_token}`);
|
||||
}
|
||||
|
||||
return await next(input, { ...init, headers });
|
||||
};
|
||||
return await next(input, { ...init, headers });
|
||||
};
|
||||
|
||||
let response = await makeRequest();
|
||||
let response = await makeRequest();
|
||||
|
||||
// Handle 401 responses by attempting re-authentication
|
||||
if (response.status === 401) {
|
||||
try {
|
||||
const resourceMetadataUrl = extractResourceMetadataUrl(response);
|
||||
// Handle 401 responses by attempting re-authentication
|
||||
if (response.status === 401) {
|
||||
try {
|
||||
const resourceMetadataUrl = extractResourceMetadataUrl(response);
|
||||
|
||||
// Use provided baseUrl or extract from request URL
|
||||
const serverUrl =
|
||||
baseUrl ||
|
||||
(typeof input === "string" ? new URL(input).origin : input.origin);
|
||||
// Use provided baseUrl or extract from request URL
|
||||
const serverUrl = baseUrl || (typeof input === 'string' ? new URL(input).origin : input.origin);
|
||||
|
||||
const result = await auth(provider, {
|
||||
serverUrl,
|
||||
resourceMetadataUrl,
|
||||
fetchFn: next,
|
||||
});
|
||||
const result = await auth(provider, {
|
||||
serverUrl,
|
||||
resourceMetadataUrl,
|
||||
fetchFn: next
|
||||
});
|
||||
|
||||
if (result === "REDIRECT") {
|
||||
throw new UnauthorizedError(
|
||||
"Authentication requires user authorization - redirect initiated",
|
||||
);
|
||||
}
|
||||
if (result === 'REDIRECT') {
|
||||
throw new UnauthorizedError('Authentication requires user authorization - redirect initiated');
|
||||
}
|
||||
|
||||
if (result !== "AUTHORIZED") {
|
||||
throw new UnauthorizedError(
|
||||
`Authentication failed with result: ${result}`,
|
||||
);
|
||||
}
|
||||
if (result !== 'AUTHORIZED') {
|
||||
throw new UnauthorizedError(`Authentication failed with result: ${result}`);
|
||||
}
|
||||
|
||||
// Retry the request with fresh tokens
|
||||
response = await makeRequest();
|
||||
} catch (error) {
|
||||
if (error instanceof UnauthorizedError) {
|
||||
throw error;
|
||||
}
|
||||
throw new UnauthorizedError(
|
||||
`Failed to re-authenticate: ${error instanceof Error ? error.message : String(error)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
// Retry the request with fresh tokens
|
||||
response = await makeRequest();
|
||||
} catch (error) {
|
||||
if (error instanceof UnauthorizedError) {
|
||||
throw error;
|
||||
}
|
||||
throw new UnauthorizedError(`Failed to re-authenticate: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// If we still have a 401 after re-auth attempt, throw an error
|
||||
if (response.status === 401) {
|
||||
const url = typeof input === "string" ? input : input.toString();
|
||||
throw new UnauthorizedError(`Authentication failed for ${url}`);
|
||||
}
|
||||
// If we still have a 401 after re-auth attempt, throw an error
|
||||
if (response.status === 401) {
|
||||
const url = typeof input === 'string' ? input : input.toString();
|
||||
throw new UnauthorizedError(`Authentication failed for ${url}`);
|
||||
}
|
||||
|
||||
return response;
|
||||
return response;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Logger function type for HTTP requests
|
||||
*/
|
||||
export type RequestLogger = (input: {
|
||||
method: string;
|
||||
url: string | URL;
|
||||
status: number;
|
||||
statusText: string;
|
||||
duration: number;
|
||||
requestHeaders?: Headers;
|
||||
responseHeaders?: Headers;
|
||||
error?: Error;
|
||||
method: string;
|
||||
url: string | URL;
|
||||
status: number;
|
||||
statusText: string;
|
||||
duration: number;
|
||||
requestHeaders?: Headers;
|
||||
responseHeaders?: Headers;
|
||||
error?: Error;
|
||||
}) => void;
|
||||
|
||||
/**
|
||||
* Configuration options for the logging middleware
|
||||
*/
|
||||
export type LoggingOptions = {
|
||||
/**
|
||||
* Custom logger function, defaults to console logging
|
||||
*/
|
||||
logger?: RequestLogger;
|
||||
/**
|
||||
* Custom logger function, defaults to console logging
|
||||
*/
|
||||
logger?: RequestLogger;
|
||||
|
||||
/**
|
||||
* Whether to include request headers in logs
|
||||
* @default false
|
||||
*/
|
||||
includeRequestHeaders?: boolean;
|
||||
/**
|
||||
* Whether to include request headers in logs
|
||||
* @default false
|
||||
*/
|
||||
includeRequestHeaders?: boolean;
|
||||
|
||||
/**
|
||||
* Whether to include response headers in logs
|
||||
* @default false
|
||||
*/
|
||||
includeResponseHeaders?: boolean;
|
||||
/**
|
||||
* Whether to include response headers in logs
|
||||
* @default false
|
||||
*/
|
||||
includeResponseHeaders?: boolean;
|
||||
|
||||
/**
|
||||
* Status level filter - only log requests with status >= this value
|
||||
* Set to 0 to log all requests, 400 to log only errors
|
||||
* @default 0
|
||||
*/
|
||||
statusLevel?: number;
|
||||
/**
|
||||
* Status level filter - only log requests with status >= this value
|
||||
* Set to 0 to log all requests, 400 to log only errors
|
||||
* @default 0
|
||||
*/
|
||||
statusLevel?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -166,100 +153,82 @@ export type LoggingOptions = {
|
|||
* @returns A fetch middleware function
|
||||
*/
|
||||
export const withLogging = (options: LoggingOptions = {}): Middleware => {
|
||||
const {
|
||||
logger,
|
||||
includeRequestHeaders = false,
|
||||
includeResponseHeaders = false,
|
||||
statusLevel = 0,
|
||||
} = options;
|
||||
const { logger, includeRequestHeaders = false, includeResponseHeaders = false, statusLevel = 0 } = options;
|
||||
|
||||
const defaultLogger: RequestLogger = (input) => {
|
||||
const {
|
||||
method,
|
||||
url,
|
||||
status,
|
||||
statusText,
|
||||
duration,
|
||||
requestHeaders,
|
||||
responseHeaders,
|
||||
error,
|
||||
} = input;
|
||||
const defaultLogger: RequestLogger = input => {
|
||||
const { method, url, status, statusText, duration, requestHeaders, responseHeaders, error } = input;
|
||||
|
||||
let message = error
|
||||
? `HTTP ${method} ${url} failed: ${error.message} (${duration}ms)`
|
||||
: `HTTP ${method} ${url} ${status} ${statusText} (${duration}ms)`;
|
||||
let message = error
|
||||
? `HTTP ${method} ${url} failed: ${error.message} (${duration}ms)`
|
||||
: `HTTP ${method} ${url} ${status} ${statusText} (${duration}ms)`;
|
||||
|
||||
// Add headers to message if requested
|
||||
if (includeRequestHeaders && requestHeaders) {
|
||||
const reqHeaders = Array.from(requestHeaders.entries())
|
||||
.map(([key, value]) => `${key}: ${value}`)
|
||||
.join(", ");
|
||||
message += `\n Request Headers: {${reqHeaders}}`;
|
||||
}
|
||||
// Add headers to message if requested
|
||||
if (includeRequestHeaders && requestHeaders) {
|
||||
const reqHeaders = Array.from(requestHeaders.entries())
|
||||
.map(([key, value]) => `${key}: ${value}`)
|
||||
.join(', ');
|
||||
message += `\n Request Headers: {${reqHeaders}}`;
|
||||
}
|
||||
|
||||
if (includeResponseHeaders && responseHeaders) {
|
||||
const resHeaders = Array.from(responseHeaders.entries())
|
||||
.map(([key, value]) => `${key}: ${value}`)
|
||||
.join(", ");
|
||||
message += `\n Response Headers: {${resHeaders}}`;
|
||||
}
|
||||
if (includeResponseHeaders && responseHeaders) {
|
||||
const resHeaders = Array.from(responseHeaders.entries())
|
||||
.map(([key, value]) => `${key}: ${value}`)
|
||||
.join(', ');
|
||||
message += `\n Response Headers: {${resHeaders}}`;
|
||||
}
|
||||
|
||||
if (error || status >= 400) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(message);
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(message);
|
||||
}
|
||||
};
|
||||
if (error || status >= 400) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(message);
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(message);
|
||||
}
|
||||
};
|
||||
|
||||
const logFn = logger || defaultLogger;
|
||||
const logFn = logger || defaultLogger;
|
||||
|
||||
return (next) => async (input, init) => {
|
||||
const startTime = performance.now();
|
||||
const method = init?.method || "GET";
|
||||
const url = typeof input === "string" ? input : input.toString();
|
||||
const requestHeaders = includeRequestHeaders
|
||||
? new Headers(init?.headers)
|
||||
: undefined;
|
||||
return next => async (input, init) => {
|
||||
const startTime = performance.now();
|
||||
const method = init?.method || 'GET';
|
||||
const url = typeof input === 'string' ? input : input.toString();
|
||||
const requestHeaders = includeRequestHeaders ? new Headers(init?.headers) : undefined;
|
||||
|
||||
try {
|
||||
const response = await next(input, init);
|
||||
const duration = performance.now() - startTime;
|
||||
try {
|
||||
const response = await next(input, init);
|
||||
const duration = performance.now() - startTime;
|
||||
|
||||
// Only log if status meets the log level threshold
|
||||
if (response.status >= statusLevel) {
|
||||
logFn({
|
||||
method,
|
||||
url,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
duration,
|
||||
requestHeaders,
|
||||
responseHeaders: includeResponseHeaders
|
||||
? response.headers
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
// Only log if status meets the log level threshold
|
||||
if (response.status >= statusLevel) {
|
||||
logFn({
|
||||
method,
|
||||
url,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
duration,
|
||||
requestHeaders,
|
||||
responseHeaders: includeResponseHeaders ? response.headers : undefined
|
||||
});
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
const duration = performance.now() - startTime;
|
||||
return response;
|
||||
} catch (error) {
|
||||
const duration = performance.now() - startTime;
|
||||
|
||||
// Always log errors regardless of log level
|
||||
logFn({
|
||||
method,
|
||||
url,
|
||||
status: 0,
|
||||
statusText: "Network Error",
|
||||
duration,
|
||||
requestHeaders,
|
||||
error: error as Error,
|
||||
});
|
||||
// Always log errors regardless of log level
|
||||
logFn({
|
||||
method,
|
||||
url,
|
||||
status: 0,
|
||||
statusText: 'Network Error',
|
||||
duration,
|
||||
requestHeaders,
|
||||
error: error as Error
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -281,12 +250,10 @@ export const withLogging = (options: LoggingOptions = {}): Middleware => {
|
|||
* @param middleware - Array of fetch middleware to compose into a pipeline
|
||||
* @returns A single composed middleware function
|
||||
*/
|
||||
export const applyMiddlewares = (
|
||||
...middleware: Middleware[]
|
||||
): Middleware => {
|
||||
return (next) => {
|
||||
return middleware.reduce((handler, mw) => mw(handler), next);
|
||||
};
|
||||
export const applyMiddlewares = (...middleware: Middleware[]): Middleware => {
|
||||
return next => {
|
||||
return middleware.reduce((handler, mw) => mw(handler), next);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -347,12 +314,6 @@ export const applyMiddlewares = (
|
|||
* @param handler - Function that receives the next handler and request parameters
|
||||
* @returns A fetch middleware function
|
||||
*/
|
||||
export const createMiddleware = (
|
||||
handler: (
|
||||
next: FetchLike,
|
||||
input: string | URL,
|
||||
init?: RequestInit,
|
||||
) => Promise<Response>,
|
||||
): Middleware => {
|
||||
return (next) => (input, init) => handler(next, input as string | URL, init);
|
||||
export const createMiddleware = (handler: (next: FetchLike, input: string | URL, init?: RequestInit) => Promise<Response>): Middleware => {
|
||||
return next => (input, init) => handler(next, input as string | URL, init);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue