BREAKING CHANGE(core): major architectural refactoring with fetch-like API
Some checks failed
Default (tags) / security (push) Failing after 24s
Default (tags) / test (push) Failing after 13s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped

This commit is contained in:
2025-07-27 21:23:20 +00:00
parent f7d2c6de4f
commit bbb57004d9
24 changed files with 1038 additions and 593 deletions

View File

@@ -1,6 +1,5 @@
import { type ISmartRequestOptions } from '../legacy/smartrequest.interfaces.js';
import { request, type IExtendedIncomingMessage } from '../legacy/smartrequest.request.js';
import * as plugins from '../legacy/smartrequest.plugins.js';
import { request, SmartResponse, type ICoreRequestOptions } from '../core/index.js';
import * as plugins from '../core/plugins.js';
import type { HttpMethod, ResponseType, FormField } from './types/common.js';
import {
@@ -18,9 +17,7 @@ import { createPaginatedResponse } from './features/pagination.js';
*/
export class SmartRequestClient<T = any> {
private _url: string;
private _options: ISmartRequestOptions = {};
private _responseType: ResponseType = 'json';
private _timeoutMs: number = 60000;
private _options: ICoreRequestOptions = {};
private _retries: number = 0;
private _queryParams: Record<string, string> = {};
private _paginationConfig?: TPaginationConfig;
@@ -94,7 +91,6 @@ export class SmartRequestClient<T = any> {
* Set request timeout in milliseconds
*/
timeout(ms: number): this {
this._timeoutMs = ms;
this._options.timeout = ms;
this._options.hardDataCuttingTimeout = ms;
return this;
@@ -145,16 +141,18 @@ export class SmartRequestClient<T = any> {
}
/**
* Set response type
* Set the Accept header to indicate what content type is expected
*/
responseType(type: ResponseType): this {
this._responseType = type;
if (type === 'binary' || type === 'stream') {
this._options.autoJsonParse = false;
}
return this;
accept(type: ResponseType): this {
// Map response types to Accept header values
const acceptHeaders: Record<ResponseType, string> = {
'json': 'application/json',
'text': 'text/plain',
'binary': 'application/octet-stream',
'stream': '*/*'
};
return this.header('Accept', acceptHeaders[type]);
}
/**
@@ -225,35 +223,35 @@ export class SmartRequestClient<T = any> {
/**
* Make a GET request
*/
async get<R = T>(): Promise<IExtendedIncomingMessage<R>> {
async get<R = T>(): Promise<SmartResponse<R>> {
return this.execute<R>('GET');
}
/**
* Make a POST request
*/
async post<R = T>(): Promise<IExtendedIncomingMessage<R>> {
async post<R = T>(): Promise<SmartResponse<R>> {
return this.execute<R>('POST');
}
/**
* Make a PUT request
*/
async put<R = T>(): Promise<IExtendedIncomingMessage<R>> {
async put<R = T>(): Promise<SmartResponse<R>> {
return this.execute<R>('PUT');
}
/**
* Make a DELETE request
*/
async delete<R = T>(): Promise<IExtendedIncomingMessage<R>> {
async delete<R = T>(): Promise<SmartResponse<R>> {
return this.execute<R>('DELETE');
}
/**
* Make a PATCH request
*/
async patch<R = T>(): Promise<IExtendedIncomingMessage<R>> {
async patch<R = T>(): Promise<SmartResponse<R>> {
return this.execute<R>('PATCH');
}
@@ -272,7 +270,7 @@ export class SmartRequestClient<T = any> {
const response = await this.execute();
return createPaginatedResponse<ItemType>(
return await createPaginatedResponse<ItemType>(
response,
this._paginationConfig,
this._queryParams,
@@ -298,7 +296,7 @@ export class SmartRequestClient<T = any> {
/**
* Execute the HTTP request
*/
private async execute<R = T>(method?: HttpMethod): Promise<IExtendedIncomingMessage<R>> {
private async execute<R = T>(method?: HttpMethod): Promise<SmartResponse<R>> {
if (method) {
this._options.method = method;
}
@@ -310,28 +308,8 @@ export class SmartRequestClient<T = any> {
for (let attempt = 0; attempt <= this._retries; attempt++) {
try {
if (this._responseType === 'stream') {
return await request(this._url, this._options, true) as IExtendedIncomingMessage<R>;
} else if (this._responseType === 'binary') {
const response = await request(this._url, this._options, true);
// Handle binary response
const dataPromise = plugins.smartpromise.defer<Buffer>();
const chunks: Buffer[] = [];
response.on('data', (chunk: Buffer) => chunks.push(chunk));
response.on('end', () => {
const buffer = Buffer.concat(chunks);
(response as IExtendedIncomingMessage<R>).body = buffer as any;
dataPromise.resolve();
});
await dataPromise.promise;
return response as IExtendedIncomingMessage<R>;
} else {
// Handle JSON or text response
return await request(this._url, this._options) as IExtendedIncomingMessage<R>;
}
const response = await request(this._url, this._options);
return response as SmartResponse<R>;
} catch (error) {
lastError = error as Error;