@lytjs/common-http 6.5.0 → 6.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +257 -0
- package/dist/index.cjs +68 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +49 -2
- package/dist/index.d.ts +49 -2
- package/dist/index.mjs +58 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +38 -35
- package/src/index.ts +481 -334
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { stringifyQueryString } from '@lytjs/common-query';
|
|
2
|
+
|
|
1
3
|
// src/index.ts
|
|
2
4
|
var HttpError = class extends Error {
|
|
3
5
|
constructor(message, response) {
|
|
@@ -68,14 +70,18 @@ var HttpClient = class {
|
|
|
68
70
|
let httpResponse = await this._parseResponse(response, config.responseType);
|
|
69
71
|
for (const interceptor of this._interceptors) {
|
|
70
72
|
if (interceptor.response) {
|
|
71
|
-
httpResponse = await interceptor.response(
|
|
73
|
+
httpResponse = await interceptor.response(
|
|
74
|
+
httpResponse
|
|
75
|
+
);
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
return httpResponse;
|
|
75
79
|
} catch (err) {
|
|
76
80
|
for (const interceptor of this._interceptors) {
|
|
77
81
|
if (interceptor.error) {
|
|
78
|
-
const result = interceptor.error(
|
|
82
|
+
const result = interceptor.error(
|
|
83
|
+
err instanceof HttpError ? err : new HttpError(String(err))
|
|
84
|
+
);
|
|
79
85
|
if (result !== void 0) return result;
|
|
80
86
|
}
|
|
81
87
|
}
|
|
@@ -122,8 +128,7 @@ var HttpClient = class {
|
|
|
122
128
|
_resolveURL(base, url, params) {
|
|
123
129
|
let resolved = base ? base.replace(/\/+$/, "") + "/" + url.replace(/^\/+/, "") : url;
|
|
124
130
|
if (params) {
|
|
125
|
-
const
|
|
126
|
-
const qs = searchParams.toString();
|
|
131
|
+
const qs = stringifyQueryString(params);
|
|
127
132
|
if (qs) {
|
|
128
133
|
resolved += (resolved.includes("?") ? "&" : "?") + qs;
|
|
129
134
|
}
|
|
@@ -142,10 +147,14 @@ var HttpClient = class {
|
|
|
142
147
|
clearTimeout(timeoutId);
|
|
143
148
|
throw new HttpError("Request was aborted", void 0);
|
|
144
149
|
}
|
|
145
|
-
signal.addEventListener(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
150
|
+
signal.addEventListener(
|
|
151
|
+
"abort",
|
|
152
|
+
() => {
|
|
153
|
+
clearTimeout(timeoutId);
|
|
154
|
+
timeoutController.abort();
|
|
155
|
+
},
|
|
156
|
+
{ once: true }
|
|
157
|
+
);
|
|
149
158
|
}
|
|
150
159
|
}
|
|
151
160
|
const fetchOptions = {
|
|
@@ -165,10 +174,7 @@ var HttpClient = class {
|
|
|
165
174
|
headers: this._parseHeaders(response.headers),
|
|
166
175
|
ok: false
|
|
167
176
|
};
|
|
168
|
-
throw new HttpError(
|
|
169
|
-
`HTTP ${response.status}: ${response.statusText}`,
|
|
170
|
-
errorResponse
|
|
171
|
-
);
|
|
177
|
+
throw new HttpError(`HTTP ${response.status}: ${response.statusText}`, errorResponse);
|
|
172
178
|
}
|
|
173
179
|
return response;
|
|
174
180
|
} finally {
|
|
@@ -216,7 +222,46 @@ function createHttpClient(options) {
|
|
|
216
222
|
return new HttpClient(options);
|
|
217
223
|
}
|
|
218
224
|
var http = new HttpClient();
|
|
225
|
+
function get(url, options) {
|
|
226
|
+
return http.get(url, options);
|
|
227
|
+
}
|
|
228
|
+
function post(url, data, options) {
|
|
229
|
+
return http.post(url, data, options);
|
|
230
|
+
}
|
|
231
|
+
function put(url, data, options) {
|
|
232
|
+
return http.put(url, data, options);
|
|
233
|
+
}
|
|
234
|
+
function del(url, options) {
|
|
235
|
+
return http.delete(url, options);
|
|
236
|
+
}
|
|
237
|
+
function patch(url, data, options) {
|
|
238
|
+
return http.patch(url, data, options);
|
|
239
|
+
}
|
|
240
|
+
async function requestJson(method, url, options) {
|
|
241
|
+
const { data, ...config } = options || {};
|
|
242
|
+
if (method === "GET" || method === "DELETE") {
|
|
243
|
+
const response2 = await http.request(method, url, config);
|
|
244
|
+
return response2.data;
|
|
245
|
+
}
|
|
246
|
+
const response = await http.request(method, url, { ...config, body: data });
|
|
247
|
+
return response.data;
|
|
248
|
+
}
|
|
249
|
+
async function getJson(url, options) {
|
|
250
|
+
return requestJson("GET", url, options);
|
|
251
|
+
}
|
|
252
|
+
async function postJson(url, data, options) {
|
|
253
|
+
return requestJson("POST", url, { ...options, data });
|
|
254
|
+
}
|
|
255
|
+
async function putJson(url, data, options) {
|
|
256
|
+
return requestJson("PUT", url, { ...options, data });
|
|
257
|
+
}
|
|
258
|
+
async function patchJson(url, data, options) {
|
|
259
|
+
return requestJson("PATCH", url, { ...options, data });
|
|
260
|
+
}
|
|
261
|
+
async function deleteJson(url, options) {
|
|
262
|
+
return requestJson("DELETE", url, options);
|
|
263
|
+
}
|
|
219
264
|
|
|
220
|
-
export { CancellationToken, HttpClient, HttpError, createHttpClient, http };
|
|
265
|
+
export { CancellationToken, HttpClient, HttpError, createHttpClient, del, deleteJson, get, getJson, http, patch, patchJson, post, postJson, put, putJson, requestJson };
|
|
221
266
|
//# sourceMappingURL=index.mjs.map
|
|
222
267
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * @lytjs/common-http\r\n * Lightweight HTTP client based on native fetch API\r\n */\r\n\r\n// --- Types ---\r\n\r\nexport interface HttpClientOptions {\r\n baseURL?: string;\r\n headers?: Record<string, string>;\r\n timeout?: number;\r\n withCredentials?: boolean;\r\n}\r\n\r\nexport interface RequestOptions {\r\n headers?: Record<string, string>;\r\n params?: Record<string, string>;\r\n timeout?: number;\r\n signal?: AbortSignal;\r\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';\r\n}\r\n\r\nexport interface HttpResponse<T> {\r\n data: T;\r\n status: number;\r\n statusText: string;\r\n headers: Record<string, string>;\r\n ok: boolean;\r\n}\r\n\r\nexport interface InternalRequestConfig {\r\n method: string;\r\n url: string;\r\n headers: Record<string, string>;\r\n body?: BodyInit | null;\r\n signal?: AbortSignal;\r\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';\r\n withCredentials?: boolean;\r\n timeout?: number;\r\n}\r\n\r\nexport interface Interceptor {\r\n request?(config: InternalRequestConfig): InternalRequestConfig | Promise<InternalRequestConfig>;\r\n response?(response: HttpResponse<unknown>): HttpResponse<unknown> | Promise<HttpResponse<unknown>>;\r\n error?(error: HttpError): unknown;\r\n}\r\n\r\n// --- HttpError ---\r\n\r\nexport class HttpError extends Error {\r\n readonly response?: HttpResponse<unknown>;\r\n readonly status?: number;\r\n\r\n constructor(message: string, response?: HttpResponse<unknown>) {\r\n super(message);\r\n this.name = 'HttpError';\r\n this.response = response;\r\n this.status = response?.status;\r\n }\r\n}\r\n\r\n// --- CancellationToken ---\r\n\r\nexport class CancellationToken {\r\n private readonly _controller: AbortController;\r\n private readonly _linkedTokens: CancellationToken[];\r\n\r\n constructor() {\r\n this._controller = new AbortController();\r\n this._linkedTokens = [];\r\n }\r\n\r\n get signal(): AbortSignal {\r\n return this._controller.signal;\r\n }\r\n\r\n cancel(): void {\r\n this._controller.abort();\r\n for (const token of this._linkedTokens) {\r\n token.cancel();\r\n }\r\n }\r\n\r\n get isCancelled(): boolean {\r\n return this._controller.signal.aborted;\r\n }\r\n\r\n static createLinkedToken(...tokens: CancellationToken[]): CancellationToken {\r\n const linked = new CancellationToken();\r\n for (const token of tokens) {\r\n token._linkedTokens.push(linked);\r\n if (token.isCancelled) {\r\n linked.cancel();\r\n return linked;\r\n }\r\n }\r\n return linked;\r\n }\r\n}\r\n\r\n// --- HttpClient ---\r\n\r\nexport class HttpClient {\r\n private readonly _options: HttpClientOptions;\r\n private readonly _interceptors: Interceptor[];\r\n\r\n constructor(options?: HttpClientOptions) {\r\n this._options = { ...options };\r\n this._interceptors = [];\r\n }\r\n\r\n get<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\r\n return this.request<T>('GET', url, options);\r\n }\r\n\r\n post<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>> {\r\n return this.request<T>('POST', url, { ...options, body: data } as RequestOptions & { body?: unknown });\r\n }\r\n\r\n put<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>> {\r\n return this.request<T>('PUT', url, { ...options, body: data } as RequestOptions & { body?: unknown });\r\n }\r\n\r\n delete<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\r\n return this.request<T>('DELETE', url, options);\r\n }\r\n\r\n patch<T = unknown>(url: string, data?: unknown, options?: RequestOptions): Promise<HttpResponse<T>> {\r\n return this.request<T>('PATCH', url, { ...options, body: data } as RequestOptions & { body?: unknown });\r\n }\r\n\r\n async request<T = unknown>(\r\n method: string,\r\n url: string,\r\n options?: RequestOptions & { body?: unknown },\r\n ): Promise<HttpResponse<T>> {\r\n let config = this._buildConfig(method, url, options);\r\n\r\n // Apply request interceptors\r\n for (const interceptor of this._interceptors) {\r\n if (interceptor.request) {\r\n config = await interceptor.request(config);\r\n }\r\n }\r\n\r\n try {\r\n const response = await this._fetch(config);\r\n let httpResponse = await this._parseResponse<T>(response, config.responseType);\r\n\r\n // Apply response interceptors\r\n for (const interceptor of this._interceptors) {\r\n if (interceptor.response) {\r\n httpResponse = (await interceptor.response(httpResponse as HttpResponse<unknown>)) as HttpResponse<T>;\r\n }\r\n }\r\n\r\n return httpResponse;\r\n } catch (err) {\r\n // Apply error interceptors\r\n for (const interceptor of this._interceptors) {\r\n if (interceptor.error) {\r\n const result = interceptor.error(err instanceof HttpError ? err : new HttpError(String(err)));\r\n if (result !== undefined) return result as HttpResponse<T>;\r\n }\r\n }\r\n throw err;\r\n }\r\n }\r\n\r\n use(interceptor: Interceptor): () => void {\r\n this._interceptors.push(interceptor);\r\n return () => this.eject(interceptor);\r\n }\r\n\r\n eject(interceptor: Interceptor): void {\r\n const index = this._interceptors.indexOf(interceptor);\r\n if (index !== -1) {\r\n this._interceptors.splice(index, 1);\r\n }\r\n }\r\n\r\n private _buildConfig(\r\n method: string,\r\n url: string,\r\n options?: RequestOptions & { body?: unknown },\r\n ): InternalRequestConfig {\r\n const { baseURL = '', headers: defaultHeaders = {} } = this._options;\r\n const resolvedURL = this._resolveURL(baseURL, url, options?.params);\r\n\r\n const headers: Record<string, string> = { ...defaultHeaders, ...options?.headers };\r\n\r\n let body: BodyInit | null = null;\r\n if (options && 'body' in options && options.body !== undefined) {\r\n if (typeof options.body === 'object' && options.body !== null) {\r\n body = JSON.stringify(options.body);\r\n if (!headers['Content-Type']) {\r\n headers['Content-Type'] = 'application/json';\r\n }\r\n } else {\r\n body = String(options.body);\r\n }\r\n }\r\n\r\n const timeout = options?.timeout ?? this._options.timeout;\r\n\r\n return {\r\n method: method.toUpperCase(),\r\n url: resolvedURL,\r\n headers,\r\n body,\r\n signal: options?.signal,\r\n responseType: options?.responseType,\r\n withCredentials: this._options.withCredentials,\r\n timeout,\r\n };\r\n }\r\n\r\n private _resolveURL(base: string, url: string, params?: Record<string, string>): string {\r\n let resolved = base ? base.replace(/\\/+$/, '') + '/' + url.replace(/^\\/+/, '') : url;\r\n if (params) {\r\n const searchParams = new URLSearchParams(params);\r\n const qs = searchParams.toString();\r\n if (qs) {\r\n resolved += (resolved.includes('?') ? '&' : '?') + qs;\r\n }\r\n }\r\n return resolved;\r\n }\r\n\r\n private async _fetch(config: InternalRequestConfig): Promise<Response> {\r\n const { method, url, headers, body, signal, withCredentials, timeout } = config;\r\n\r\n // Handle timeout via AbortController\r\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\r\n let timeoutController: AbortController | undefined;\r\n\r\n if (timeout && timeout > 0) {\r\n timeoutController = new AbortController();\r\n timeoutId = setTimeout(() => timeoutController!.abort(), timeout);\r\n\r\n // Link with existing signal\r\n if (signal) {\r\n if (signal.aborted) {\r\n clearTimeout(timeoutId);\r\n throw new HttpError('Request was aborted', undefined);\r\n }\r\n signal.addEventListener('abort', () => {\r\n clearTimeout(timeoutId);\r\n timeoutController!.abort();\r\n }, { once: true });\r\n }\r\n }\r\n\r\n const fetchOptions: RequestInit = {\r\n method,\r\n headers,\r\n body,\r\n credentials: withCredentials ? 'include' : undefined,\r\n signal: timeoutController ? timeoutController.signal : signal,\r\n };\r\n\r\n try {\r\n const response = await fetch(url, fetchOptions);\r\n\r\n if (!response.ok) {\r\n const errorResponse: HttpResponse<unknown> = {\r\n data: null,\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers: this._parseHeaders(response.headers),\r\n ok: false,\r\n };\r\n throw new HttpError(\r\n `HTTP ${response.status}: ${response.statusText}`,\r\n errorResponse,\r\n );\r\n }\r\n\r\n return response;\r\n } finally {\r\n if (timeoutId !== undefined) {\r\n clearTimeout(timeoutId);\r\n }\r\n }\r\n }\r\n\r\n private async _parseResponse<T>(\r\n response: Response,\r\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer',\r\n ): Promise<HttpResponse<T>> {\r\n let data: T;\r\n switch (responseType) {\r\n case 'text':\r\n data = (await response.text()) as unknown as T;\r\n break;\r\n case 'blob':\r\n data = (await response.blob()) as unknown as T;\r\n break;\r\n case 'arraybuffer':\r\n data = (await response.arrayBuffer()) as unknown as T;\r\n break;\r\n case 'json':\r\n default: {\r\n const text = await response.text();\r\n data = text ? JSON.parse(text) : (null as unknown as T);\r\n break;\r\n }\r\n }\r\n\r\n return {\r\n data,\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers: this._parseHeaders(response.headers),\r\n ok: response.ok,\r\n };\r\n }\r\n\r\n private _parseHeaders(headers: Headers): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n headers.forEach((value, key) => {\r\n result[key] = value;\r\n });\r\n return result;\r\n }\r\n}\r\n\r\n// --- Convenience exports ---\r\n\r\nexport function createHttpClient(options?: HttpClientOptions): HttpClient {\r\n return new HttpClient(options);\r\n}\r\n\r\nexport const http: HttpClient = new HttpClient();\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["response"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @lytjs/common-http\n * Lightweight HTTP client based on native fetch API\n */\n\n// --- Imports ---\nimport { stringifyQueryString } from '@lytjs/common-query';\n\n// --- Types ---\n\nexport interface HttpClientOptions {\n baseURL?: string;\n headers?: Record<string, string>;\n timeout?: number;\n withCredentials?: boolean;\n}\n\nexport interface RequestOptions {\n headers?: Record<string, string>;\n params?: Record<string, string | number | boolean | Array<string | number | boolean>>;\n timeout?: number;\n signal?: AbortSignal;\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';\n}\n\nexport interface HttpResponse<T> {\n data: T;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n ok: boolean;\n}\n\nexport interface InternalRequestConfig {\n method: string;\n url: string;\n headers: Record<string, string>;\n body?: BodyInit | null;\n signal?: AbortSignal;\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer';\n withCredentials?: boolean;\n timeout?: number;\n}\n\nexport interface Interceptor {\n request?(config: InternalRequestConfig): InternalRequestConfig | Promise<InternalRequestConfig>;\n response?(\n response: HttpResponse<unknown>,\n ): HttpResponse<unknown> | Promise<HttpResponse<unknown>>;\n error?(error: HttpError): unknown;\n}\n\n// --- HttpError ---\n\nexport class HttpError extends Error {\n readonly response?: HttpResponse<unknown>;\n readonly status?: number;\n\n constructor(message: string, response?: HttpResponse<unknown>) {\n super(message);\n this.name = 'HttpError';\n this.response = response;\n this.status = response?.status;\n }\n}\n\n// --- CancellationToken ---\n\nexport class CancellationToken {\n private readonly _controller: AbortController;\n private readonly _linkedTokens: CancellationToken[];\n\n constructor() {\n this._controller = new AbortController();\n this._linkedTokens = [];\n }\n\n get signal(): AbortSignal {\n return this._controller.signal;\n }\n\n cancel(): void {\n this._controller.abort();\n for (const token of this._linkedTokens) {\n token.cancel();\n }\n }\n\n get isCancelled(): boolean {\n return this._controller.signal.aborted;\n }\n\n static createLinkedToken(...tokens: CancellationToken[]): CancellationToken {\n const linked = new CancellationToken();\n for (const token of tokens) {\n token._linkedTokens.push(linked);\n if (token.isCancelled) {\n linked.cancel();\n return linked;\n }\n }\n return linked;\n }\n}\n\n// --- HttpClient ---\n\nexport class HttpClient {\n private readonly _options: HttpClientOptions;\n private readonly _interceptors: Interceptor[];\n\n constructor(options?: HttpClientOptions) {\n this._options = { ...options };\n this._interceptors = [];\n }\n\n get<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\n return this.request<T>('GET', url, options);\n }\n\n post<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<HttpResponse<T>> {\n return this.request<T>('POST', url, { ...options, body: data } as RequestOptions & {\n body?: unknown;\n });\n }\n\n put<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<HttpResponse<T>> {\n return this.request<T>('PUT', url, { ...options, body: data } as RequestOptions & {\n body?: unknown;\n });\n }\n\n delete<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\n return this.request<T>('DELETE', url, options);\n }\n\n patch<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n ): Promise<HttpResponse<T>> {\n return this.request<T>('PATCH', url, { ...options, body: data } as RequestOptions & {\n body?: unknown;\n });\n }\n\n async request<T = unknown>(\n method: string,\n url: string,\n options?: RequestOptions & { body?: unknown },\n ): Promise<HttpResponse<T>> {\n let config = this._buildConfig(method, url, options);\n\n // Apply request interceptors\n for (const interceptor of this._interceptors) {\n if (interceptor.request) {\n config = await interceptor.request(config);\n }\n }\n\n try {\n const response = await this._fetch(config);\n let httpResponse = await this._parseResponse<T>(response, config.responseType);\n\n // Apply response interceptors\n for (const interceptor of this._interceptors) {\n if (interceptor.response) {\n httpResponse = (await interceptor.response(\n httpResponse as HttpResponse<unknown>,\n )) as HttpResponse<T>;\n }\n }\n\n return httpResponse;\n } catch (err) {\n // Apply error interceptors\n for (const interceptor of this._interceptors) {\n if (interceptor.error) {\n const result = interceptor.error(\n err instanceof HttpError ? err : new HttpError(String(err)),\n );\n if (result !== undefined) return result as HttpResponse<T>;\n }\n }\n throw err;\n }\n }\n\n use(interceptor: Interceptor): () => void {\n this._interceptors.push(interceptor);\n return () => this.eject(interceptor);\n }\n\n eject(interceptor: Interceptor): void {\n const index = this._interceptors.indexOf(interceptor);\n if (index !== -1) {\n this._interceptors.splice(index, 1);\n }\n }\n\n private _buildConfig(\n method: string,\n url: string,\n options?: RequestOptions & { body?: unknown },\n ): InternalRequestConfig {\n const { baseURL = '', headers: defaultHeaders = {} } = this._options;\n const resolvedURL = this._resolveURL(baseURL, url, options?.params);\n\n const headers: Record<string, string> = { ...defaultHeaders, ...options?.headers };\n\n let body: BodyInit | null = null;\n if (options && 'body' in options && options.body !== undefined) {\n if (typeof options.body === 'object' && options.body !== null) {\n body = JSON.stringify(options.body);\n if (!headers['Content-Type']) {\n headers['Content-Type'] = 'application/json';\n }\n } else {\n body = String(options.body);\n }\n }\n\n const timeout = options?.timeout ?? this._options.timeout;\n\n return {\n method: method.toUpperCase(),\n url: resolvedURL,\n headers,\n body,\n signal: options?.signal,\n responseType: options?.responseType,\n withCredentials: this._options.withCredentials,\n timeout,\n };\n }\n\n private _resolveURL(\n base: string,\n url: string,\n params?: Record<string, string | number | boolean | Array<string | number | boolean>>,\n ): string {\n let resolved = base ? base.replace(/\\/+$/, '') + '/' + url.replace(/^\\/+/, '') : url;\n if (params) {\n const qs = stringifyQueryString(params);\n if (qs) {\n resolved += (resolved.includes('?') ? '&' : '?') + qs;\n }\n }\n return resolved;\n }\n\n private async _fetch(config: InternalRequestConfig): Promise<Response> {\n const { method, url, headers, body, signal, withCredentials, timeout } = config;\n\n // Handle timeout via AbortController\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let timeoutController: AbortController | undefined;\n\n if (timeout && timeout > 0) {\n timeoutController = new AbortController();\n timeoutId = setTimeout(() => timeoutController!.abort(), timeout);\n\n // Link with existing signal\n if (signal) {\n if (signal.aborted) {\n clearTimeout(timeoutId);\n throw new HttpError('Request was aborted', undefined);\n }\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timeoutId);\n timeoutController!.abort();\n },\n { once: true },\n );\n }\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n body,\n credentials: withCredentials ? 'include' : undefined,\n signal: timeoutController ? timeoutController.signal : signal,\n };\n\n try {\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n const errorResponse: HttpResponse<unknown> = {\n data: null,\n status: response.status,\n statusText: response.statusText,\n headers: this._parseHeaders(response.headers),\n ok: false,\n };\n throw new HttpError(`HTTP ${response.status}: ${response.statusText}`, errorResponse);\n }\n\n return response;\n } finally {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n private async _parseResponse<T>(\n response: Response,\n responseType?: 'json' | 'text' | 'blob' | 'arraybuffer',\n ): Promise<HttpResponse<T>> {\n let data: T;\n switch (responseType) {\n case 'text':\n data = (await response.text()) as unknown as T;\n break;\n case 'blob':\n data = (await response.blob()) as unknown as T;\n break;\n case 'arraybuffer':\n data = (await response.arrayBuffer()) as unknown as T;\n break;\n case 'json':\n default: {\n const text = await response.text();\n data = text ? JSON.parse(text) : (null as unknown as T);\n break;\n }\n }\n\n return {\n data,\n status: response.status,\n statusText: response.statusText,\n headers: this._parseHeaders(response.headers),\n ok: response.ok,\n };\n }\n\n private _parseHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n }\n}\n\n// --- Convenience exports ---\n\nexport function createHttpClient(options?: HttpClientOptions): HttpClient {\n return new HttpClient(options);\n}\n\nexport const http: HttpClient = new HttpClient();\n\n// --- Convenience methods for the default http client ---\n\n/**\n * 便捷 GET 请求\n */\nexport function get<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\n return http.get<T>(url, options);\n}\n\n/**\n * 便捷 POST 请求\n */\nexport function post<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<HttpResponse<T>> {\n return http.post<T>(url, data, options);\n}\n\n/**\n * 便捷 PUT 请求\n */\nexport function put<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<HttpResponse<T>> {\n return http.put<T>(url, data, options);\n}\n\n/**\n * 便捷 DELETE 请求\n */\nexport function del<T = unknown>(url: string, options?: RequestOptions): Promise<HttpResponse<T>> {\n return http.delete<T>(url, options);\n}\n\n/**\n * 便捷 PATCH 请求\n */\nexport function patch<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<HttpResponse<T>> {\n return http.patch<T>(url, data, options);\n}\n\n/**\n * 发送 JSON 请求并直接获取数据\n * 自动处理响应解析和错误\n */\nexport async function requestJson<T = unknown>(\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n url: string,\n options?: RequestOptions & { data?: unknown },\n): Promise<T> {\n const { data, ...config } = options || {};\n\n if (method === 'GET' || method === 'DELETE') {\n const response = await http.request<T>(method, url, config);\n return response.data;\n }\n\n const response = await http.request<T>(method, url, { ...config, body: data });\n return response.data;\n}\n\n/**\n * 发送 GET JSON 请求\n */\nexport async function getJson<T = unknown>(url: string, options?: RequestOptions): Promise<T> {\n return requestJson<T>('GET', url, options);\n}\n\n/**\n * 发送 POST JSON 请求\n */\nexport async function postJson<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<T> {\n return requestJson<T>('POST', url, { ...options, data });\n}\n\n/**\n * 发送 PUT JSON 请求\n */\nexport async function putJson<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<T> {\n return requestJson<T>('PUT', url, { ...options, data });\n}\n\n/**\n * 发送 PATCH JSON 请求\n */\nexport async function patchJson<T = unknown>(\n url: string,\n data?: unknown,\n options?: RequestOptions,\n): Promise<T> {\n return requestJson<T>('PATCH', url, { ...options, data });\n}\n\n/**\n * 发送 DELETE JSON 请求\n */\nexport async function deleteJson<T = unknown>(url: string, options?: RequestOptions): Promise<T> {\n return requestJson<T>('DELETE', url, options);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,35 +1,38 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@lytjs/common-http",
|
|
3
|
-
"version": "6.
|
|
4
|
-
"description": "Lightweight HTTP client
|
|
5
|
-
"main": "./dist/index.cjs",
|
|
6
|
-
"module": "./dist/index.mjs",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"import": "./dist/index.mjs",
|
|
12
|
-
"require": "./dist/index.cjs"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"files": [
|
|
16
|
-
"dist",
|
|
17
|
-
"src"
|
|
18
|
-
],
|
|
19
|
-
"scripts": {
|
|
20
|
-
"test": "vitest run",
|
|
21
|
-
"test:watch": "vitest",
|
|
22
|
-
"test:coverage": "vitest run --coverage",
|
|
23
|
-
"lint": "eslint \"src/**/*.ts\"",
|
|
24
|
-
"build": "tsup",
|
|
25
|
-
"type-check": "tsc --noEmit",
|
|
26
|
-
"clean": "rm -rf dist"
|
|
27
|
-
},
|
|
28
|
-
"sideEffects": false,
|
|
29
|
-
"license": "MIT",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@lytjs/common-http",
|
|
3
|
+
"version": "6.6.0",
|
|
4
|
+
"description": "Lightweight HTTP client based on native fetch API",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"test:coverage": "vitest run --coverage",
|
|
23
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
24
|
+
"build": "tsup",
|
|
25
|
+
"type-check": "tsc --noEmit",
|
|
26
|
+
"clean": "rm -rf dist"
|
|
27
|
+
},
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@lytjs/common-query": "workspace:*"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"tsup": "^8.4.0",
|
|
35
|
+
"typescript": "^5.8.2",
|
|
36
|
+
"vitest": "^3.0.7"
|
|
37
|
+
}
|
|
38
|
+
}
|