2017-07-06 20:58:01 +02:00
|
|
|
let shim = {};
|
|
|
|
|
2017-07-10 20:09:58 +02:00
|
|
|
shim.isNode = () => {
|
2018-03-09 22:59:12 +02:00
|
|
|
if (typeof process === 'undefined') return false;
|
2017-11-11 00:18:00 +02:00
|
|
|
if (shim.isElectron()) return true;
|
2018-03-09 22:59:12 +02:00
|
|
|
return process.title == 'node';
|
2017-07-10 20:09:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
shim.isReactNative = () => {
|
|
|
|
return !shim.isNode();
|
|
|
|
};
|
|
|
|
|
2017-11-14 20:02:58 +02:00
|
|
|
shim.isLinux = () => {
|
2018-03-09 22:59:12 +02:00
|
|
|
return process && process.platform === 'linux';
|
|
|
|
}
|
2017-11-14 20:02:58 +02:00
|
|
|
|
|
|
|
shim.isWindows = () => {
|
2018-03-09 22:59:12 +02:00
|
|
|
return process && process.platform === 'win32';
|
|
|
|
}
|
2017-11-14 20:02:58 +02:00
|
|
|
|
|
|
|
shim.isMac = () => {
|
2018-03-09 22:59:12 +02:00
|
|
|
return process && process.platform === 'darwin';
|
|
|
|
}
|
2017-11-14 20:02:58 +02:00
|
|
|
|
2018-02-16 20:08:02 +02:00
|
|
|
shim.platformName = function() {
|
2018-03-09 22:59:12 +02:00
|
|
|
if (shim.isReactNative()) return 'mobile';
|
|
|
|
if (shim.isMac()) return 'darwin';
|
|
|
|
if (shim.isWindows()) return 'win32';
|
|
|
|
if (shim.isLinux()) return 'linux';
|
|
|
|
throw new Error('Cannot determine platform');
|
|
|
|
}
|
2018-02-16 20:08:02 +02:00
|
|
|
|
2017-11-11 00:18:00 +02:00
|
|
|
// https://github.com/cheton/is-electron
|
|
|
|
shim.isElectron = () => {
|
2017-11-14 20:02:58 +02:00
|
|
|
// Renderer process
|
2018-03-09 22:59:12 +02:00
|
|
|
if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') {
|
2017-11-14 20:02:58 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Main process
|
2018-03-09 22:59:12 +02:00
|
|
|
if (typeof process !== 'undefined' && typeof process.versions === 'object' && !!process.versions.electron) {
|
2017-11-14 20:02:58 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Detect the user agent when the `nodeIntegration` option is set to true
|
2018-03-09 22:59:12 +02:00
|
|
|
if (typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('Electron') >= 0) {
|
2017-11-14 20:02:58 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2018-03-09 22:59:12 +02:00
|
|
|
}
|
2017-11-11 00:18:00 +02:00
|
|
|
|
2017-11-13 00:52:54 +02:00
|
|
|
// Node requests can go wrong is so many different ways and with so
|
|
|
|
// many different error messages... This handler inspects the error
|
|
|
|
// and decides whether the request can safely be repeated or not.
|
2018-03-09 21:51:01 +02:00
|
|
|
shim.fetchRequestCanBeRetried = function(error) {
|
2017-11-14 20:02:58 +02:00
|
|
|
if (!error) return false;
|
|
|
|
|
|
|
|
// Unfortunately the error 'Network request failed' doesn't have a type
|
|
|
|
// or error code, so hopefully that message won't change and is not localized
|
2018-03-09 22:59:12 +02:00
|
|
|
if (error.message == 'Network request failed') return true;
|
2017-11-14 20:02:58 +02:00
|
|
|
|
|
|
|
// request to https://public-ch3302....1fab24cb1bd5f.md failed, reason: socket hang up"
|
2018-03-09 22:59:12 +02:00
|
|
|
if (error.code == 'ECONNRESET') return true;
|
2017-11-14 20:02:58 +02:00
|
|
|
|
|
|
|
// OneDrive (or Node?) sometimes sends back a "not found" error for resources
|
|
|
|
// that definitely exist and in this case repeating the request works.
|
|
|
|
// Error is:
|
2018-03-09 22:59:12 +02:00
|
|
|
// request to https://graph.microsoft.com/v1.0/drive/special/approot failed, reason: getaddrinfo ENOTFOUND graph.microsoft.com graph.microsoft.com:443
|
|
|
|
if (error.code == 'ENOTFOUND') return true;
|
2017-11-14 20:02:58 +02:00
|
|
|
|
|
|
|
// network timeout at: https://public-ch3302...859f9b0e3ab.md
|
2018-03-09 22:59:12 +02:00
|
|
|
if (error.message && error.message.indexOf('network timeout') === 0) return true;
|
2017-11-14 20:02:58 +02:00
|
|
|
|
|
|
|
// name: 'FetchError',
|
|
|
|
// message: 'request to https://api.ipify.org/?format=json failed, reason: getaddrinfo EAI_AGAIN api.ipify.org:443',
|
|
|
|
// type: 'system',
|
|
|
|
// errno: 'EAI_AGAIN',
|
|
|
|
// code: 'EAI_AGAIN' } } reason: { FetchError: request to https://api.ipify.org/?format=json failed, reason: getaddrinfo EAI_AGAIN api.ipify.org:443
|
|
|
|
//
|
|
|
|
// It's a Microsoft error: "A temporary failure in name resolution occurred."
|
2018-03-09 22:59:12 +02:00
|
|
|
if (error.code == 'EAI_AGAIN') return true;
|
2017-11-14 20:02:58 +02:00
|
|
|
|
|
|
|
// request to https://public-...8fd8bc6bb68e9c4d17a.md failed, reason: connect ETIMEDOUT 204.79.197.213:443
|
|
|
|
// Code: ETIMEDOUT
|
2018-03-09 22:59:12 +02:00
|
|
|
if (error.code === 'ETIMEDOUT') return true;
|
2017-11-14 20:02:58 +02:00
|
|
|
|
2018-03-27 18:48:55 +02:00
|
|
|
// ECONNREFUSED is generally temporary
|
|
|
|
if (error.code === 'ECONNREFUSED') return true;
|
|
|
|
|
2017-11-14 20:02:58 +02:00
|
|
|
return false;
|
2018-03-09 21:51:01 +02:00
|
|
|
};
|
2017-11-13 00:52:54 +02:00
|
|
|
|
|
|
|
shim.fetchWithRetry = async function(fetchFn, options = null) {
|
2018-03-09 22:59:12 +02:00
|
|
|
const { time } = require('lib/time-utils.js');
|
2017-11-14 20:02:58 +02:00
|
|
|
|
|
|
|
if (!options) options = {};
|
|
|
|
if (!options.timeout) options.timeout = 1000 * 120; // ms
|
2018-03-09 22:59:12 +02:00
|
|
|
if (!('maxRetry' in options)) options.maxRetry = 5;
|
2017-11-14 20:02:58 +02:00
|
|
|
|
|
|
|
let retryCount = 0;
|
|
|
|
while (true) {
|
|
|
|
try {
|
|
|
|
const response = await fetchFn();
|
|
|
|
return response;
|
|
|
|
} catch (error) {
|
2018-03-09 21:51:01 +02:00
|
|
|
if (shim.fetchRequestCanBeRetried(error)) {
|
2017-11-14 20:02:58 +02:00
|
|
|
retryCount++;
|
|
|
|
if (retryCount > options.maxRetry) throw error;
|
|
|
|
await time.sleep(retryCount * 3);
|
|
|
|
} else {
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-03-09 22:59:12 +02:00
|
|
|
}
|
2017-11-13 00:52:54 +02:00
|
|
|
|
2018-03-09 22:59:12 +02:00
|
|
|
shim.fetch = () => { throw new Error('Not implemented'); }
|
|
|
|
shim.FormData = typeof FormData !== 'undefined' ? FormData : null;
|
|
|
|
shim.fsDriver = () => { throw new Error('Not implemented') }
|
2017-07-24 20:01:40 +02:00
|
|
|
shim.FileApiDriverLocal = null;
|
2018-03-09 22:59:12 +02:00
|
|
|
shim.readLocalFileBase64 = (path) => { throw new Error('Not implemented'); }
|
|
|
|
shim.uploadBlob = () => { throw new Error('Not implemented'); }
|
2017-12-12 01:52:42 +02:00
|
|
|
shim.sjclModule = null;
|
2018-03-09 22:59:12 +02:00
|
|
|
shim.randomBytes = async (count) => { throw new Error('Not implemented'); }
|
2017-11-05 02:17:48 +02:00
|
|
|
shim.setInterval = function(fn, interval) {
|
|
|
|
return setInterval(fn, interval);
|
2018-03-09 22:59:12 +02:00
|
|
|
}
|
2017-11-05 02:17:48 +02:00
|
|
|
shim.clearInterval = function(id) {
|
|
|
|
return clearInterval(id);
|
2018-03-09 22:59:12 +02:00
|
|
|
}
|
|
|
|
shim.stringByteLength = function(string) { throw new Error('Not implemented'); }
|
2017-11-04 14:23:46 +02:00
|
|
|
shim.detectAndSetLocale = null;
|
2018-03-09 22:59:12 +02:00
|
|
|
shim.attachFileToNote = async (note, filePath) => {}
|
2018-03-24 21:35:10 +02:00
|
|
|
shim.Buffer = null;
|
2018-03-27 01:55:44 +02:00
|
|
|
shim.openUrl = () => { throw new Error('Not implemented'); }
|
2017-07-06 20:58:01 +02:00
|
|
|
|
2018-03-09 22:59:12 +02:00
|
|
|
module.exports = { shim };
|