76 lines
2.0 KiB
JavaScript
76 lines
2.0 KiB
JavaScript
'use strict';
|
|
|
|
const testPath = "npm2url/dist/index.cjs";
|
|
const defaultProviders = {
|
|
jsdelivr: (path) => `https://cdn.jsdelivr.net/npm/${path}`,
|
|
unpkg: (path) => `https://unpkg.com/${path}`
|
|
};
|
|
async function checkUrl(url, signal) {
|
|
const res = await fetch(url, {
|
|
signal
|
|
});
|
|
if (!res.ok) {
|
|
throw res;
|
|
}
|
|
await res.text();
|
|
}
|
|
class UrlBuilder {
|
|
constructor() {
|
|
this.providers = { ...defaultProviders };
|
|
this.provider = "jsdelivr";
|
|
}
|
|
/**
|
|
* Get the fastest provider name.
|
|
* If none of the providers returns a valid response within `timeout`, an error will be thrown.
|
|
*/
|
|
async getFastestProvider(timeout = 5e3, path = testPath) {
|
|
const controller = new AbortController();
|
|
let timer = 0;
|
|
try {
|
|
return await new Promise((resolve, reject) => {
|
|
Promise.all(
|
|
Object.entries(this.providers).map(async ([name, factory]) => {
|
|
try {
|
|
await checkUrl(factory(path), controller.signal);
|
|
resolve(name);
|
|
} catch {
|
|
}
|
|
})
|
|
).then(() => reject(new Error("All providers failed")));
|
|
timer = setTimeout(reject, timeout, new Error("Timed out"));
|
|
});
|
|
} finally {
|
|
controller.abort();
|
|
clearTimeout(timer);
|
|
}
|
|
}
|
|
/**
|
|
* Set the current provider to the fastest provider found by `getFastestProvider`.
|
|
*/
|
|
async findFastestProvider(timeout, path) {
|
|
this.provider = await this.getFastestProvider(timeout, path);
|
|
return this.provider;
|
|
}
|
|
setProvider(name, factory) {
|
|
if (factory) {
|
|
this.providers[name] = factory;
|
|
} else {
|
|
delete this.providers[name];
|
|
}
|
|
}
|
|
getFullUrl(path, provider = this.provider) {
|
|
if (path.includes("://")) {
|
|
return path;
|
|
}
|
|
const factory = this.providers[provider];
|
|
if (!factory) {
|
|
throw new Error(`Provider ${provider} not found`);
|
|
}
|
|
return factory(path);
|
|
}
|
|
}
|
|
const urlBuilder = new UrlBuilder();
|
|
|
|
exports.UrlBuilder = UrlBuilder;
|
|
exports.urlBuilder = urlBuilder;
|