BREAKING CHANGE(core): major architectural refactoring with fetch-like API
This commit is contained in:
242
ts/legacy/adapter.ts
Normal file
242
ts/legacy/adapter.ts
Normal file
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
* Legacy adapter that provides backward compatibility
|
||||
* Maps legacy API to the new core module
|
||||
*/
|
||||
|
||||
import * as core from '../core/index.js';
|
||||
import * as plugins from '../core/plugins.js';
|
||||
|
||||
const smartpromise = plugins.smartpromise;
|
||||
|
||||
// Re-export types for backward compatibility
|
||||
export { type IExtendedIncomingMessage } from '../core/types.js';
|
||||
export interface ISmartRequestOptions extends core.ICoreRequestOptions {
|
||||
autoJsonParse?: boolean;
|
||||
responseType?: 'json' | 'text' | 'binary' | 'stream';
|
||||
}
|
||||
|
||||
// Re-export interface for form fields
|
||||
export interface IFormField {
|
||||
name: string;
|
||||
type: 'string' | 'filePath' | 'Buffer';
|
||||
payload: string | Buffer;
|
||||
fileName?: string;
|
||||
contentType?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to convert stream to IExtendedIncomingMessage for legacy compatibility
|
||||
*/
|
||||
async function streamToExtendedMessage(
|
||||
stream: plugins.http.IncomingMessage,
|
||||
autoJsonParse = true
|
||||
): Promise<core.IExtendedIncomingMessage> {
|
||||
const done = smartpromise.defer<core.IExtendedIncomingMessage>();
|
||||
const chunks: Buffer[] = [];
|
||||
|
||||
stream.on('data', (chunk: Buffer) => {
|
||||
chunks.push(chunk);
|
||||
});
|
||||
|
||||
stream.on('end', () => {
|
||||
const buffer = Buffer.concat(chunks);
|
||||
const extendedMessage = stream as core.IExtendedIncomingMessage;
|
||||
|
||||
if (autoJsonParse) {
|
||||
const text = buffer.toString('utf-8');
|
||||
try {
|
||||
extendedMessage.body = JSON.parse(text);
|
||||
} catch (err) {
|
||||
extendedMessage.body = text;
|
||||
}
|
||||
} else {
|
||||
extendedMessage.body = buffer;
|
||||
}
|
||||
|
||||
done.resolve(extendedMessage);
|
||||
});
|
||||
|
||||
stream.on('error', (err) => {
|
||||
done.reject(err);
|
||||
});
|
||||
|
||||
return done.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy request function that returns IExtendedIncomingMessage
|
||||
*/
|
||||
export async function request(
|
||||
urlArg: string,
|
||||
optionsArg: ISmartRequestOptions = {},
|
||||
responseStreamArg = false,
|
||||
requestDataFunc?: (req: plugins.http.ClientRequest) => void
|
||||
): Promise<core.IExtendedIncomingMessage> {
|
||||
const stream = await core.coreRequest(urlArg, optionsArg, requestDataFunc);
|
||||
|
||||
if (responseStreamArg) {
|
||||
// For stream responses, just cast and return
|
||||
return stream as core.IExtendedIncomingMessage;
|
||||
}
|
||||
|
||||
// Convert stream to IExtendedIncomingMessage
|
||||
const autoJsonParse = optionsArg.autoJsonParse !== false;
|
||||
return streamToExtendedMessage(stream, autoJsonParse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe GET request
|
||||
*/
|
||||
export async function safeGet(urlArg: string): Promise<core.IExtendedIncomingMessage | null> {
|
||||
const agentToUse = urlArg.startsWith('http://')
|
||||
? new plugins.http.Agent()
|
||||
: new plugins.https.Agent();
|
||||
|
||||
try {
|
||||
const response = await request(urlArg, {
|
||||
method: 'GET',
|
||||
agent: agentToUse,
|
||||
timeout: 5000,
|
||||
hardDataCuttingTimeout: 5000,
|
||||
autoJsonParse: false,
|
||||
});
|
||||
return response;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET JSON request
|
||||
*/
|
||||
export async function getJson(urlArg: string, optionsArg: ISmartRequestOptions = {}) {
|
||||
optionsArg.method = 'GET';
|
||||
return request(urlArg, optionsArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST JSON request
|
||||
*/
|
||||
export async function postJson(urlArg: string, optionsArg: ISmartRequestOptions = {}) {
|
||||
optionsArg.method = 'POST';
|
||||
if (
|
||||
typeof optionsArg.requestBody === 'object' &&
|
||||
(!optionsArg.headers || !optionsArg.headers['Content-Type'])
|
||||
) {
|
||||
// make sure headers exist
|
||||
if (!optionsArg.headers) {
|
||||
optionsArg.headers = {};
|
||||
}
|
||||
|
||||
// assign the right Content-Type, leaving all other headers in place
|
||||
optionsArg.headers = {
|
||||
...optionsArg.headers,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
}
|
||||
return request(urlArg, optionsArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT JSON request
|
||||
*/
|
||||
export async function putJson(urlArg: string, optionsArg: ISmartRequestOptions = {}) {
|
||||
optionsArg.method = 'PUT';
|
||||
return request(urlArg, optionsArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE JSON request
|
||||
*/
|
||||
export async function delJson(urlArg: string, optionsArg: ISmartRequestOptions = {}) {
|
||||
optionsArg.method = 'DELETE';
|
||||
return request(urlArg, optionsArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET binary data
|
||||
*/
|
||||
export async function getBinary(urlArg: string, optionsArg: ISmartRequestOptions = {}) {
|
||||
optionsArg = {
|
||||
...optionsArg,
|
||||
autoJsonParse: false,
|
||||
responseType: 'binary'
|
||||
};
|
||||
return request(urlArg, optionsArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST form data
|
||||
*/
|
||||
export async function postFormData(urlArg: string, formFields: IFormField[], optionsArg: ISmartRequestOptions = {}) {
|
||||
const form = new plugins.formData();
|
||||
|
||||
for (const formField of formFields) {
|
||||
if (formField.type === 'filePath') {
|
||||
const fileData = plugins.fs.readFileSync(
|
||||
plugins.path.isAbsolute(formField.payload as string)
|
||||
? formField.payload as string
|
||||
: plugins.path.join(process.cwd(), formField.payload as string)
|
||||
);
|
||||
form.append(formField.name, fileData, {
|
||||
filename: formField.fileName || plugins.path.basename(formField.payload as string),
|
||||
contentType: formField.contentType
|
||||
});
|
||||
} else if (formField.type === 'Buffer') {
|
||||
form.append(formField.name, formField.payload, {
|
||||
filename: formField.fileName,
|
||||
contentType: formField.contentType
|
||||
});
|
||||
} else {
|
||||
form.append(formField.name, formField.payload);
|
||||
}
|
||||
}
|
||||
|
||||
optionsArg.method = 'POST';
|
||||
optionsArg.requestBody = form;
|
||||
if (!optionsArg.headers) {
|
||||
optionsArg.headers = {};
|
||||
}
|
||||
optionsArg.headers = {
|
||||
...optionsArg.headers,
|
||||
...form.getHeaders()
|
||||
};
|
||||
|
||||
return request(urlArg, optionsArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST URL encoded form data
|
||||
*/
|
||||
export async function postFormDataUrlEncoded(
|
||||
urlArg: string,
|
||||
formFields: { key: string; content: string }[],
|
||||
optionsArg: ISmartRequestOptions = {}
|
||||
) {
|
||||
optionsArg.method = 'POST';
|
||||
if (!optionsArg.headers) {
|
||||
optionsArg.headers = {};
|
||||
}
|
||||
optionsArg.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
|
||||
const urlEncodedBody = formFields
|
||||
.map(field => `${encodeURIComponent(field.key)}=${encodeURIComponent(field.content)}`)
|
||||
.join('&');
|
||||
|
||||
optionsArg.requestBody = urlEncodedBody;
|
||||
|
||||
return request(urlArg, optionsArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET stream
|
||||
*/
|
||||
export async function getStream(
|
||||
urlArg: string,
|
||||
optionsArg: ISmartRequestOptions = {}
|
||||
): Promise<plugins.http.IncomingMessage> {
|
||||
optionsArg.method = 'GET';
|
||||
const response = await request(urlArg, optionsArg, true);
|
||||
return response;
|
||||
}
|
Reference in New Issue
Block a user