ngx-uploadx
Version:
Angular Resumable Upload Module
90 lines • 12.7 kB
JavaScript
function safeMatch(base, re) {
return (base.match(re) || [''])[0];
}
export function resolveUrl(url, base) {
if (url.indexOf('https://') * url.indexOf('http://') === 0)
return url;
if (url.indexOf('//') === 0)
return safeMatch(base, /^(https?:)/) + url;
if (url.indexOf('/') === 0)
return safeMatch(base, /^(?:https?:)?(?:\/\/)?([^\/?]+)/) + url;
return safeMatch(base, /^(?:https?:)?(?:\/\/)?([^\/?]+)?(.*\/)/) + url;
}
/**
* Unwraps a value if it is a function, otherwise returns the value directly.
* Useful for allowing values to optionally be specified as functions.
*/
export function unfunc(value, ref) {
return value instanceof Function ? value(ref) : value;
}
export const pick = (obj, props) => {
const result = {};
props.forEach(key => (result[key] = obj[key]));
return result;
};
export function isNumber(x) {
return x === Number(x);
}
/**
* 32-bit FNV-1a hash function
*/
export function createHash(str) {
let hash = 2166136261;
const len = str.length;
for (let i = 0; i < len; i++) {
hash ^= str.charCodeAt(i);
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
}
return hash >>> 0;
}
/**
* Utility functions for base64 encoding and decoding strings and objects.
*/
export const b64 = {
encode: (str) => btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => String.fromCharCode(Number.parseInt(p1, 16)))),
decode: (str) => decodeURIComponent(atob(str)
.split('')
.map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
.join('')),
serialize: (obj) => Object.keys(obj)
.map(key => [key, b64.encode(String(obj[key]))].filter(Boolean).join(' '))
.toString(),
parse: (encoded) => {
const kvPairs = encoded.split(',').map(kv => kv.split(' '));
const decoded = {};
for (const [key, value] of kvPairs) {
if (key)
decoded[key] = value ? b64.decode(value) : '';
}
return decoded;
}
};
export function isBrowser() {
return ![typeof window, typeof navigator].includes('undefined');
}
export function onLine() {
return isBrowser() ? navigator.onLine : true;
}
export function isIOS() {
return isBrowser() && /iPad|iPhone/.test(navigator.userAgent);
}
export function osVersion() {
const m = /OS (\d+)_(\d+)_?(\d+)?/.exec(navigator.userAgent);
if (m?.length)
return m[1] + '.' + m[2] + '.' + m[3] || '0';
return;
}
export function compareVersions(a, b) {
return a.localeCompare(b, undefined, { numeric: true });
}
export function isBadIOS() {
return isIOS() && compareVersions(osVersion() || '0.0', '15.3') < 0;
}
/**
* [Big files upload error with iOS](https://github.com/kukhariev/ngx-uploadx/issues/316)
* TODO: move to app
*/
export const iosOverride = isBadIOS()
? { chunkSize: 0, retryConfig: { shouldRetry: () => false } }
: {};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXBsb2FkeC9saWIvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsU0FBUyxTQUFTLENBQUMsSUFBWSxFQUFFLEVBQVU7SUFDekMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3JDLENBQUM7QUFFRCxNQUFNLFVBQVUsVUFBVSxDQUFDLEdBQVcsRUFBRSxJQUFZO0lBQ2xELElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUM7UUFBRSxPQUFPLEdBQUcsQ0FBQztJQUN2RSxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUFFLE9BQU8sU0FBUyxDQUFDLElBQUksRUFBRSxZQUFZLENBQUMsR0FBRyxHQUFHLENBQUM7SUFDeEUsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQyxJQUFJLEVBQUUsaUNBQWlDLENBQUMsR0FBRyxHQUFHLENBQUM7SUFDNUYsT0FBTyxTQUFTLENBQUMsSUFBSSxFQUFFLHdDQUF3QyxDQUFDLEdBQUcsR0FBRyxDQUFDO0FBQ3pFLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsTUFBTSxDQUFPLEtBQTBCLEVBQUUsR0FBTTtJQUM3RCxPQUFPLEtBQUssWUFBWSxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0FBQ3hELENBQUM7QUFFRCxNQUFNLENBQUMsTUFBTSxJQUFJLEdBQUcsQ0FBdUIsR0FBTSxFQUFFLEtBQVUsRUFBYyxFQUFFO0lB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QUksZUFBZSxDQUFDLFNBQVMsRUFBRSxJQUFJLEtBQUssRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDdEUsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxRQUFRLEVBQUU7SUFDbkMsQ0FBQyxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxXQUFXLEVBQUUsRUFBRSxXQUFXLEVBQUUsR0FBRyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUU7SUFDN0QsQ0FBQyxDQUFDLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImZ1bmN0aW9uIHNhZmVNYXRjaChiYXNlOiBzdHJpbmcsIHJlOiBSZWdFeHApOiBzdHJpbmcge1xuICByZXR1cm4gKGJhc2UubWF0Y2gocmUpIHx8IFsnJ10pWzBdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVVybCh1cmw6IHN0cmluZywgYmFzZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHVybC5pbmRleE9mKCdodHRwczovLycpICogdXJsLmluZGV4T2YoJ2h0dHA6Ly8nKSA9PT0gMCkgcmV0dXJuIHVybDtcbiAgaWYgKHVybC5pbmRleE9mKCcvLycpID09PSAwKSByZXR1cm4gc2FmZU1hdGNoKGJhc2UsIC9eKGh0dHBzPzopLykgKyB1cmw7XG4gIGlmICh1cmwuaW5kZXhPZignLycpID09PSAwKSByZXR1cm4gc2FmZU1hdGNoKGJhc2UsIC9eKD86aHR0cHM/Oik/KD86XFwvXFwvKT8oW15cXC8/XSspLykgKyB1cmw7XG4gIHJldHVybiBzYWZlTWF0Y2goYmFzZSwgL14oPzpodHRwcz86KT8oPzpcXC9cXC8pPyhbXlxcLz9dKyk/KC4qXFwvKS8pICsgdXJsO1xufVxuXG4vKipcbiAqIFVud3JhcHMgYSB2YWx1ZSBpZiBpdCBpcyBhIGZ1bmN0aW9uLCBvdGhlcndpc2UgcmV0dXJucyB0aGUgdmFsdWUgZGlyZWN0bHkuXG4gKiBVc2VmdWwgZm9yIGFsbG93aW5nIHZhbHVlcyB0byBvcHRpb25hbGx5IGJlIHNwZWNpZmllZCBhcyBmdW5jdGlvbnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bmZ1bmM8VCwgVj4odmFsdWU6IFQgfCAoKHJlZjogVikgPT4gVCksIHJlZjogVik6IFQge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbiA/IHZhbHVlKHJlZikgOiB2YWx1ZTtcbn1cblxuZXhwb3J0IGNvbnN0IHBpY2sgPSA8VCwgSyBleHRlbmRzIGtleW9mIFQ+KG9iajogVCwgcHJvcHM6IEtbXSk6IFBpY2s8VCwgSz4gPT4ge1xuICBjb25zdCByZXN1bHQgPSB7fSBhcyBQaWNrPFQsIEs+O1xuICBwcm9wcy5mb3JFYWNoKGtleSA9PiAocmVzdWx0W2tleV0gPSBvYmpba2V5XSkpO1xuICByZXR1cm4gcmVzdWx0O1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzTnVtYmVyKHg/OiB1bmtub3duKTogeCBpcyBudW1iZXIge1xuICByZXR1cm4geCA9PT0gTnVtYmVyKHgpO1xufVxuXG4vKipcbiAqIDMyLWJpdCBGTlYtMWEgaGFzaCBmdW5jdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlSGFzaChzdHI6IHN0cmluZyk6IG51bWJlciB7XG4gIGxldCBoYXNoID0gMjE2NjEzNjI2MTtcbiAgY29uc3QgbGVuID0gc3RyLmxlbmd0aDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgIGhhc2ggXj0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgaGFzaCArPSAoaGFzaCA8PCAxKSArIChoYXNoIDw8IDQpICsgKGhhc2ggPDwgNykgKyAoaGFzaCA8PCA4KSArIChoYXNoIDw8IDI0KTtcbiAgfVxuICByZXR1cm4gaGFzaCA+Pj4gMDtcbn1cblxuLyoqXG4gKiBVdGlsaXR5IGZ1bmN0aW9ucyBmb3IgYmFzZTY0IGVuY29kaW5nIGFuZCBkZWNvZGluZyBzdHJpbmdzIGFuZCBvYmplY3RzLlxuICovXG5leHBvcnQgY29uc3QgYjY0ID0ge1xuICBlbmNvZGU6IChzdHI6IHN0cmluZyk6IHN0cmluZyA9PlxuICAgIGJ0b2EoXG4gICAgICBlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCAobWF0Y2gsIHAxKSA9PlxuICAgICAgICBTdHJpbmcuZnJvbUNoYXJDb2RlKE51bWJlci5wYXJzZUludChwMSwgMTYpKVxuICAgICAgKVxuICAgICksXG4gIGRlY29kZTogKHN0cjogc3RyaW5nKTogc3RyaW5nID0+XG4gICAgZGVjb2RlVVJJQ29tcG9uZW50KFxuICAgICAgYXRvYihzdHIpXG4gICAgICAgIC5zcGxpdCgnJylcbiAgICAgICAgLm1hcChjID0+ICclJyArICgnMDAnICsgYy5jaGFyQ29kZUF0KDApLnRvU3RyaW5nKDE2KSkuc2xpY2UoLTIpKVxuICAgICAgICAuam9pbignJylcbiAgICApLFxuXG4gIHNlcmlhbGl6ZTogKG9iajogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBzdHJpbmcgPT5cbiAgICBPYmplY3Qua2V5cyhvYmopXG4gICAgICAubWFwKGtleSA9PiBba2V5LCBiNjQuZW5jb2RlKFN0cmluZyhvYmpba2V5XSkpXS5maWx0ZXIoQm9vbGVhbikuam9pbignICcpKVxuICAgICAgLnRvU3RyaW5nKCksXG5cbiAgcGFyc2U6IChlbmNvZGVkOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0+IHtcbiAgICBjb25zdCBrdlBhaXJzID0gZW5jb2RlZC5zcGxpdCgnLCcpLm1hcChrdiA9PiBrdi5zcGxpdCgnICcpKTtcbiAgICBjb25zdCBkZWNvZGVkOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2Yga3ZQYWlycykge1xuICAgICAgaWYgKGtleSkgZGVjb2RlZFtrZXldID0gdmFsdWUgPyBiNjQuZGVjb2RlKHZhbHVlKSA6ICcnO1xuICAgIH1cbiAgICByZXR1cm4gZGVjb2RlZDtcbiAgfVxufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzQnJvd3NlcigpOiBib29sZWFuIHtcbiAgcmV0dXJuICFbdHlwZW9mIHdpbmRvdywgdHlwZW9mIG5hdmlnYXRvcl0uaW5jbHVkZXMoJ3VuZGVmaW5lZCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gb25MaW5lKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gaXNCcm93c2VyKCkgPyBuYXZpZ2F0b3Iub25MaW5lIDogdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzSU9TKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gaXNCcm93c2VyKCkgJiYgL2lQYWR8aVBob25lLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gb3NWZXJzaW9uKCkge1xuICBjb25zdCBtID0gL09TIChcXGQrKV8oXFxkKylfPyhcXGQrKT8vLmV4ZWMobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gIGlmIChtPy5sZW5ndGgpIHJldHVybiBtWzFdICsgJy4nICsgbVsyXSArICcuJyArIG1bM10gfHwgJzAnO1xuICByZXR1cm47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb21wYXJlVmVyc2lvbnMoYTogc3RyaW5nLCBiOiBzdHJpbmcpOiBudW1iZXIge1xuICByZXR1cm4gYS5sb2NhbGVDb21wYXJlKGIsIHVuZGVmaW5lZCwgeyBudW1lcmljOiB0cnVlIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNCYWRJT1MoKSB7XG4gIHJldHVybiBpc0lPUygpICYmIGNvbXBhcmVWZXJzaW9ucyhvc1ZlcnNpb24oKSB8fCAnMC4wJywgJzE1LjMnKSA8IDA7XG59XG5cbi8qKlxuICogW0JpZyBmaWxlcyB1cGxvYWQgZXJyb3Igd2l0aCBpT1NdKGh0dHBzOi8vZ2l0aHViLmNvbS9rdWtoYXJpZXYvbmd4LXVwbG9hZHgvaXNzdWVzLzMxNilcbiAqIFRPRE86IG1vdmUgdG8gYXBwXG4gKi9cbmV4cG9ydCBjb25zdCBpb3NPdmVycmlkZSA9IGlzQmFkSU9TKClcbiAgPyB7IGNodW5rU2l6ZTogMCwgcmV0cnlDb25maWc6IHsgc2hvdWxkUmV0cnk6ICgpID0+IGZhbHNlIH0gfVxuICA6IHt9O1xuIl19