@lytjs/common-http 6.5.0 → 6.7.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/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(httpResponse);
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(err instanceof HttpError ? err : new HttpError(String(err)));
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 searchParams = new URLSearchParams(params);
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("abort", () => {
146
- clearTimeout(timeoutId);
147
- timeoutController.abort();
148
- }, { once: true });
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
@@ -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,7 +1,7 @@
1
1
  {
2
2
  "name": "@lytjs/common-http",
3
- "version": "6.5.0",
4
- "description": "Lightweight HTTP client for LytJS based on native fetch API",
3
+ "version": "6.7.0",
4
+ "description": "Lightweight HTTP client based on native fetch API",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
7
7
  "types": "./dist/index.d.ts",
@@ -27,6 +27,9 @@
27
27
  },
28
28
  "sideEffects": false,
29
29
  "license": "MIT",
30
+ "dependencies": {
31
+ "@lytjs/common-query": "^6.7.0"
32
+ },
30
33
  "devDependencies": {
31
34
  "tsup": "^8.4.0",
32
35
  "typescript": "^5.8.2",