
const isFunction = (value) => typeof value === 'function';
const isUndefined = (value) => typeof value === 'undefined';

let uploadURL;

const fetch = function fetch(url, options = {}, onProgress) {
	return new Promise((resolve, reject) => {
		const xhr = new XMLHttpRequest();
		xhr.open(options.method || 'get', url);
		Object.keys(options.headers || {}).forEach((key) => {
			xhr.setRequestHeader(key, options.headers[key]);
		});
		xhr.onload = (ev) => {
			try { resolve(JSON.parse(ev.target.responseText)); }
			catch (err) { reject(err); }
		};
		xhr.onerror = reject;
		if (xhr.upload && onProgress) {
			xhr.upload.onprogress = onProgress;
		}
		xhr.send(options.body);
	});
};

const getUploadURL = (config) => {
	if (uploadURL) { return uploadURL; }

	let isHTTPS = true;
	if (!isUndefined(config.isHTTPS)) { isHTTPS = !!config.isHTTPS; }
	else {
		try { isHTTPS = window.location.protocol.toLowerCase() === 'https:'; }
		catch (err) {} // eslint-disable-line
	}
	uploadURL = isHTTPS ? '//up.qbox.me' : '//upload.qiniu.com';
	return uploadURL;
};

const validateConfig = (config) => {
	const { uptoken, uptokenUrl, uptokenFunc, domain, name } = config;
	if (!name) {
		throw new Error('name is required');
	}
	else if (!domain) {
		throw new Error('domain is required');
	}
	else if (!uptoken && !uptokenUrl && !uptokenFunc) {
		throw new Error('one of uptoken, uptokenUrl, uptokenFunc is required');
	}
	return config;
};

const generateToken = ({ uptoken, uptokenUrl, uptokenFunc }) => {
	if (uptoken) {
		return Promise.resolve(uptoken);
	}
	else if (uptokenUrl) {
		return fetch(uptokenUrl).then((data) => data.uptoken);
	}
	else if (uptokenFunc) {
		if (!isFunction(uptokenFunc)) {
			throw new Error('uptokenFunc should be a function');
		}
		return Promise.resolve(uptokenFunc());
	}
};

const responseURL = (config, data) => {
	if (data.error) {
		throw new Error(data.error);
	}
	const { domain } = config;
	const { hash, key } = data;
	const id = key ? key : hash;
	return { url: `${domain}/${id}` };
};

export default class TinyQiniu {
	constructor(config = {}) {
		this._config = validateConfig(config);
	}

	uploadFile(file, options = {}) {
		const { key, onProgress } = options;
		return generateToken(this._config)
			.then((uptoken) => {
				const formData = new FormData();
				formData.append('token', uptoken);
				formData.append('file', file);

				if (key) {
					formData.append('key', key);
				}

				return fetch(getUploadURL(this._config), {
					method: 'POST',
					body: formData
				}, onProgress).then((data) => responseURL(this._config, data));
			})
		;
	}

	uploadBase64(base64, options = {}) {
		const { base64Key } = options;

		return generateToken(this._config)
			.then((uptoken) => {
				let fetchUrl = `${getUploadURL(this._config)}/putb64/-1`;
				if (base64Key) {
					fetchUrl = `${fetchUrl}/key/${base64Key}`;
				}

				return fetch(fetchUrl, {
					method: 'POST',
					headers: {
						Authorization: `UpToken ${uptoken}`,
					},
					body: base64.split(',')[1],
				}).then((data) => responseURL(this._config, data));
			})
		;
	}
}

@@ -1954,38 +1954,8 @@
 ta;%0A
-%09const id = key ? key : hash;%0A
 %09ret
@@ -1978,18 +1978,27 @@
 main%7D/$%7B
-id
+key %7C%7C hash
 %7D%60 %7D;%0A%7D;
@@ -2399,32 +2399,156 @@
 ', key);%0A%09%09%09%09%7D%0A%0A
+%09%09%09%09console.log('scope', %60$%7Bthis._config.bucket%7D:$%7Bkey%7D%60);%0A%0A%09%09%09%09formData.append('scope', %60$%7Bthis._config.bucket%7D:$%7Bkey%7D%60);%0A%0A
 %09%09%09%09return fetch
@@ -2618,16 +2618,17 @@
 formData
+,
 %0A%09%09%09%09%7D, 

optimize src/index.js