Framework updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2026-03-04 23:20:19 +00:00
parent a89daf3d43
commit 3ed8517b2a
891 changed files with 11126 additions and 9600 deletions

View File

@@ -1,40 +1,46 @@
import platform from "../platform/index.js";
import utils from "../utils.js";
import AxiosError from "../core/AxiosError.js";
import composeSignals from "../helpers/composeSignals.js";
import {trackStream} from "../helpers/trackStream.js";
import AxiosHeaders from "../core/AxiosHeaders.js";
import {progressEventReducer, progressEventDecorator, asyncDecorator} from "../helpers/progressEventReducer.js";
import resolveConfig from "../helpers/resolveConfig.js";
import settle from "../core/settle.js";
import platform from '../platform/index.js';
import utils from '../utils.js';
import AxiosError from '../core/AxiosError.js';
import composeSignals from '../helpers/composeSignals.js';
import { trackStream } from '../helpers/trackStream.js';
import AxiosHeaders from '../core/AxiosHeaders.js';
import {
progressEventReducer,
progressEventDecorator,
asyncDecorator,
} from '../helpers/progressEventReducer.js';
import resolveConfig from '../helpers/resolveConfig.js';
import settle from '../core/settle.js';
const DEFAULT_CHUNK_SIZE = 64 * 1024;
const {isFunction} = utils;
const { isFunction } = utils;
const globalFetchAPI = (({Request, Response}) => ({
Request, Response
const globalFetchAPI = (({ Request, Response }) => ({
Request,
Response,
}))(utils.global);
const {
ReadableStream, TextEncoder
} = utils.global;
const { ReadableStream, TextEncoder } = utils.global;
const test = (fn, ...args) => {
try {
return !!fn(...args);
} catch (e) {
return false
return false;
}
}
};
const factory = (env) => {
env = utils.merge.call({
skipUndefined: true
}, globalFetchAPI, env);
env = utils.merge.call(
{
skipUndefined: true,
},
globalFetchAPI,
env
);
const {fetch: envFetch, Request, Response} = env;
const { fetch: envFetch, Request, Response } = env;
const isFetchSupported = envFetch ? isFunction(envFetch) : typeof fetch === 'function';
const isRequestSupported = isFunction(Request);
const isResponseSupported = isFunction(Response);
@@ -45,46 +51,61 @@ const factory = (env) => {
const isReadableStreamSupported = isFetchSupported && isFunction(ReadableStream);
const encodeText = isFetchSupported && (typeof TextEncoder === 'function' ?
((encoder) => (str) => encoder.encode(str))(new TextEncoder()) :
async (str) => new Uint8Array(await new Request(str).arrayBuffer())
);
const encodeText =
isFetchSupported &&
(typeof TextEncoder === 'function'
? (
(encoder) => (str) =>
encoder.encode(str)
)(new TextEncoder())
: async (str) => new Uint8Array(await new Request(str).arrayBuffer()));
const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => {
let duplexAccessed = false;
const supportsRequestStream =
isRequestSupported &&
isReadableStreamSupported &&
test(() => {
let duplexAccessed = false;
const hasContentType = new Request(platform.origin, {
body: new ReadableStream(),
method: 'POST',
get duplex() {
duplexAccessed = true;
return 'half';
},
}).headers.has('Content-Type');
const hasContentType = new Request(platform.origin, {
body: new ReadableStream(),
method: 'POST',
get duplex() {
duplexAccessed = true;
return 'half';
},
}).headers.has('Content-Type');
return duplexAccessed && !hasContentType;
});
return duplexAccessed && !hasContentType;
});
const supportsResponseStream = isResponseSupported && isReadableStreamSupported &&
const supportsResponseStream =
isResponseSupported &&
isReadableStreamSupported &&
test(() => utils.isReadableStream(new Response('').body));
const resolvers = {
stream: supportsResponseStream && ((res) => res.body)
stream: supportsResponseStream && ((res) => res.body),
};
isFetchSupported && ((() => {
['text', 'arrayBuffer', 'blob', 'formData', 'stream'].forEach(type => {
!resolvers[type] && (resolvers[type] = (res, config) => {
let method = res && res[type];
isFetchSupported &&
(() => {
['text', 'arrayBuffer', 'blob', 'formData', 'stream'].forEach((type) => {
!resolvers[type] &&
(resolvers[type] = (res, config) => {
let method = res && res[type];
if (method) {
return method.call(res);
}
if (method) {
return method.call(res);
}
throw new AxiosError(`Response type '${type}' is not supported`, AxiosError.ERR_NOT_SUPPORT, config);
})
});
})());
throw new AxiosError(
`Response type '${type}' is not supported`,
AxiosError.ERR_NOT_SUPPORT,
config
);
});
});
})();
const getBodyLength = async (body) => {
if (body == null) {
@@ -114,13 +135,13 @@ const factory = (env) => {
if (utils.isString(body)) {
return (await encodeText(body)).byteLength;
}
}
};
const resolveBodyLength = async (headers, body) => {
const length = utils.toFiniteNumber(headers.getContentLength());
return length == null ? getBodyLength(body) : length;
}
};
return async (config) => {
let {
@@ -135,38 +156,47 @@ const factory = (env) => {
responseType,
headers,
withCredentials = 'same-origin',
fetchOptions
fetchOptions,
} = resolveConfig(config);
let _fetch = envFetch || fetch;
responseType = responseType ? (responseType + '').toLowerCase() : 'text';
let composedSignal = composeSignals([signal, cancelToken && cancelToken.toAbortSignal()], timeout);
let composedSignal = composeSignals(
[signal, cancelToken && cancelToken.toAbortSignal()],
timeout
);
let request = null;
const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => {
composedSignal.unsubscribe();
});
const unsubscribe =
composedSignal &&
composedSignal.unsubscribe &&
(() => {
composedSignal.unsubscribe();
});
let requestContentLength;
try {
if (
onUploadProgress && supportsRequestStream && method !== 'get' && method !== 'head' &&
onUploadProgress &&
supportsRequestStream &&
method !== 'get' &&
method !== 'head' &&
(requestContentLength = await resolveBodyLength(headers, data)) !== 0
) {
let _request = new Request(url, {
method: 'POST',
body: data,
duplex: "half"
duplex: 'half',
});
let contentTypeHeader;
if (utils.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
headers.setContentType(contentTypeHeader)
headers.setContentType(contentTypeHeader);
}
if (_request.body) {
@@ -185,7 +215,7 @@ const factory = (env) => {
// Cloudflare Workers throws when credentials are defined
// see https://github.com/cloudflare/workerd/issues/902
const isCredentialsSupported = isRequestSupported && "credentials" in Request.prototype;
const isCredentialsSupported = isRequestSupported && 'credentials' in Request.prototype;
const resolvedOptions = {
...fetchOptions,
@@ -193,29 +223,35 @@ const factory = (env) => {
method: method.toUpperCase(),
headers: headers.normalize().toJSON(),
body: data,
duplex: "half",
credentials: isCredentialsSupported ? withCredentials : undefined
duplex: 'half',
credentials: isCredentialsSupported ? withCredentials : undefined,
};
request = isRequestSupported && new Request(url, resolvedOptions);
let response = await (isRequestSupported ? _fetch(request, fetchOptions) : _fetch(url, resolvedOptions));
let response = await (isRequestSupported
? _fetch(request, fetchOptions)
: _fetch(url, resolvedOptions));
const isStreamResponse = supportsResponseStream && (responseType === 'stream' || responseType === 'response');
const isStreamResponse =
supportsResponseStream && (responseType === 'stream' || responseType === 'response');
if (supportsResponseStream && (onDownloadProgress || (isStreamResponse && unsubscribe))) {
const options = {};
['status', 'statusText', 'headers'].forEach(prop => {
['status', 'statusText', 'headers'].forEach((prop) => {
options[prop] = response[prop];
});
const responseContentLength = utils.toFiniteNumber(response.headers.get('content-length'));
const [onProgress, flush] = onDownloadProgress && progressEventDecorator(
responseContentLength,
progressEventReducer(asyncDecorator(onDownloadProgress), true)
) || [];
const [onProgress, flush] =
(onDownloadProgress &&
progressEventDecorator(
responseContentLength,
progressEventReducer(asyncDecorator(onDownloadProgress), true)
)) ||
[];
response = new Response(
trackStream(response.body, DEFAULT_CHUNK_SIZE, onProgress, () => {
@@ -228,7 +264,10 @@ const factory = (env) => {
responseType = responseType || 'text';
let responseData = await resolvers[utils.findKey(resolvers, responseType) || 'text'](response, config);
let responseData = await resolvers[utils.findKey(resolvers, responseType) || 'text'](
response,
config
);
!isStreamResponse && unsubscribe && unsubscribe();
@@ -239,43 +278,50 @@ const factory = (env) => {
status: response.status,
statusText: response.statusText,
config,
request
})
})
request,
});
});
} catch (err) {
unsubscribe && unsubscribe();
if (err && err.name === 'TypeError' && /Load failed|fetch/i.test(err.message)) {
throw Object.assign(
new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request, err && err.response),
new AxiosError(
'Network Error',
AxiosError.ERR_NETWORK,
config,
request,
err && err.response
),
{
cause: err.cause || err
cause: err.cause || err,
}
)
);
}
throw AxiosError.from(err, err && err.code, config, request, err && err.response);
}
}
}
};
};
const seedCache = new Map();
export const getFetch = (config) => {
let env = (config && config.env) || {};
const {fetch, Request, Response} = env;
const seeds = [
Request, Response, fetch
];
const { fetch, Request, Response } = env;
const seeds = [Request, Response, fetch];
let len = seeds.length, i = len,
seed, target, map = seedCache;
let len = seeds.length,
i = len,
seed,
target,
map = seedCache;
while (i--) {
seed = seeds[i];
target = map.get(seed);
target === undefined && map.set(seed, target = (i ? new Map() : factory(env)))
target === undefined && map.set(seed, (target = i ? new Map() : factory(env)));
map = target;
}