Refactored OpenAPI

This commit is contained in:
Peng-YM 2022-05-25 11:27:53 +08:00
parent 0e46d8e14d
commit bbe29a7fac
3 changed files with 222 additions and 227 deletions

View File

@ -1,4 +1,4 @@
import { API } from '../utils/open-api';
const $ = API('sub-store');
import { OpenAPI } from '../utils/open-api';
const $ = new OpenAPI('sub-store');
export default $;

View File

@ -1,108 +1,11 @@
/* eslint-disable no-undef */
export function ENV() {
const isQX = typeof $task !== 'undefined';
const isLoon = typeof $loon !== 'undefined';
const isSurge = typeof $httpClient !== 'undefined' && !isLoon;
const isNode = eval(`typeof process !== "undefined"`);
return { isQX, isLoon, isSurge, isNode };
}
const isQX = typeof $task !== 'undefined';
const isLoon = typeof $loon !== 'undefined';
const isSurge = typeof $httpClient !== 'undefined' && !isLoon;
const isNode = eval(`typeof process !== "undefined"`);
export function HTTP(defaultOptions = { baseURL: '' }) {
const { isQX, isLoon, isSurge, isNode } = ENV();
const methods = [
'GET',
'POST',
'PUT',
'DELETE',
'HEAD',
'OPTIONS',
'PATCH',
];
const URL_REGEX =
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;
function send(method, options) {
options = typeof options === 'string' ? { url: options } : options;
const baseURL = defaultOptions.baseURL;
if (baseURL && !URL_REGEX.test(options.url || '')) {
options.url = baseURL ? baseURL + options.url : options.url;
}
options = { ...defaultOptions, ...options };
const timeout = options.timeout;
const events = {
...{
onRequest: () => {},
onResponse: (resp) => resp,
onTimeout: () => {},
},
...options.events,
};
events.onRequest(method, options);
let worker;
if (isQX) {
worker = $task.fetch({
method,
url: options.url,
headers: options.headers,
body: options.body,
});
} else if (isLoon || isSurge || isNode) {
worker = new Promise((resolve, reject) => {
const request = isNode
? eval("require('request')")
: $httpClient;
request[method.toLowerCase()](
options,
(err, response, body) => {
if (err) reject(err);
else
resolve({
statusCode:
response.status || response.statusCode,
headers: response.headers,
body,
});
},
);
});
}
let timeoutid;
const timer = timeout
? new Promise((_, reject) => {
timeoutid = setTimeout(() => {
events.onTimeout();
return reject(
`${method} URL: ${options.url} exceeds the timeout ${timeout} ms`,
);
}, timeout);
})
: null;
return (
timer
? Promise.race([timer, worker]).then((res) => {
clearTimeout(timeoutid);
return res;
})
: worker
).then((resp) => events.onResponse(resp));
}
const http = {};
methods.forEach(
(method) =>
(http[method.toLowerCase()] = (options) => send(method, options)),
);
return http;
}
export function API(name = 'untitled', debug = false) {
const { isQX, isLoon, isSurge, isNode } = ENV();
return new (class {
constructor(name, debug) {
export class OpenAPI {
constructor(name = 'untitled', debug = false) {
this.name = name;
this.debug = debug;
@ -127,10 +30,9 @@ export function API(name = 'untitled', debug = false) {
setTimeout(resolve.bind(null, v), t);
});
Promise.prototype.delay = function (t) {
return this.then(function (v) {
return delay(t, v);
});
Promise.prototype.delay = async function (t) {
const v = await this;
return await delay(t, v);
};
}
@ -140,9 +42,7 @@ export function API(name = 'untitled', debug = false) {
if (isQX)
this.cache = JSON.parse($prefs.valueForKey(this.name) || '{}');
if (isLoon || isSurge)
this.cache = JSON.parse(
$persistentStore.read(this.name) || '{}',
);
this.cache = JSON.parse($persistentStore.read(this.name) || '{}');
if (isNode) {
// create a json for root cache
@ -315,5 +215,100 @@ export function API(name = 'untitled', debug = false) {
}
}
}
})(name, debug);
}
export function ENV() {
return { isQX, isLoon, isSurge, isNode };
}
export function HTTP(defaultOptions = { baseURL: '' }) {
const { isQX, isLoon, isSurge, isNode } = ENV();
const methods = [
'GET',
'POST',
'PUT',
'DELETE',
'HEAD',
'OPTIONS',
'PATCH',
];
const URL_REGEX =
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;
function send(method, options) {
options = typeof options === 'string' ? { url: options } : options;
const baseURL = defaultOptions.baseURL;
if (baseURL && !URL_REGEX.test(options.url || '')) {
options.url = baseURL ? baseURL + options.url : options.url;
}
options = { ...defaultOptions, ...options };
const timeout = options.timeout;
const events = {
...{
onRequest: () => {},
onResponse: (resp) => resp,
onTimeout: () => {},
},
...options.events,
};
events.onRequest(method, options);
let worker;
if (isQX) {
worker = $task.fetch({
method,
url: options.url,
headers: options.headers,
body: options.body,
});
} else if (isLoon || isSurge || isNode) {
worker = new Promise((resolve, reject) => {
const request = isNode
? eval("require('request')")
: $httpClient;
request[method.toLowerCase()](
options,
(err, response, body) => {
if (err) reject(err);
else
resolve({
statusCode:
response.status || response.statusCode,
headers: response.headers,
body,
});
},
);
});
}
let timeoutid;
const timer = timeout
? new Promise((_, reject) => {
timeoutid = setTimeout(() => {
events.onTimeout();
return reject(
`${method} URL: ${options.url} exceeds the timeout ${timeout} ms`,
);
}, timeout);
})
: null;
return (
timer
? Promise.race([timer, worker]).then((res) => {
clearTimeout(timeoutid);
return res;
})
: worker
).then((resp) => events.onResponse(resp));
}
const http = {};
methods.forEach(
(method) =>
(http[method.toLowerCase()] = (options) => send(method, options)),
);
return http;
}

File diff suppressed because one or more lines are too long