|
@@ -1,4 +1,4 @@
|
|
|
-import { debounce, normalizeKeys, noop, request } from 'src/common';
|
|
|
|
|
|
|
+import { debounce, normalizeKeys, request, noop } from 'src/common';
|
|
|
import getEventEmitter from '../utils/events';
|
|
import getEventEmitter from '../utils/events';
|
|
|
import { getOption, setOption, hookOptions } from '../utils/options';
|
|
import { getOption, setOption, hookOptions } from '../utils/options';
|
|
|
import { getScriptsByIndex, parseScript, saveScript, removeScript } from '../utils/db';
|
|
import { getScriptsByIndex, parseScript, saveScript, removeScript } from '../utils/db';
|
|
@@ -108,25 +108,32 @@ export function getStates() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function serviceFactory(base) {
|
|
function serviceFactory(base) {
|
|
|
- const initService = (...args) => {
|
|
|
|
|
- const service = Object.create(base);
|
|
|
|
|
- service.initialize(...args);
|
|
|
|
|
- return service;
|
|
|
|
|
|
|
+ const Service = function constructor(...args) {
|
|
|
|
|
+ if (!(this instanceof Service)) return new Service(...args);
|
|
|
|
|
+ this.initialize(...args);
|
|
|
};
|
|
};
|
|
|
- initService.extend = options => serviceFactory(Object.assign(Object.create(base), options));
|
|
|
|
|
- return initService;
|
|
|
|
|
|
|
+ Service.prototype = base;
|
|
|
|
|
+ Service.extend = extendService;
|
|
|
|
|
+ return Service;
|
|
|
}
|
|
}
|
|
|
|
|
+function extendService(options) {
|
|
|
|
|
+ return serviceFactory(Object.assign(Object.create(this.prototype), options));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const onStateChange = debounce(() => {
|
|
|
|
|
+ browser.runtime.sendMessage({
|
|
|
|
|
+ cmd: 'UpdateSync',
|
|
|
|
|
+ data: getStates(),
|
|
|
|
|
+ });
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
export const BaseService = serviceFactory({
|
|
export const BaseService = serviceFactory({
|
|
|
name: 'base',
|
|
name: 'base',
|
|
|
displayName: 'BaseService',
|
|
displayName: 'BaseService',
|
|
|
delayTime: 1000,
|
|
delayTime: 1000,
|
|
|
urlPrefix: '',
|
|
urlPrefix: '',
|
|
|
metaFile: 'Violentmonkey',
|
|
metaFile: 'Violentmonkey',
|
|
|
- delay(time) {
|
|
|
|
|
- return new Promise(resolve => { setTimeout(resolve, time); });
|
|
|
|
|
- },
|
|
|
|
|
initialize(name) {
|
|
initialize(name) {
|
|
|
- this.onStateChange = debounce(this.onStateChange.bind(this));
|
|
|
|
|
if (name) this.name = name;
|
|
if (name) this.name = name;
|
|
|
this.progress = {
|
|
this.progress = {
|
|
|
finished: 0,
|
|
finished: 0,
|
|
@@ -140,13 +147,13 @@ export const BaseService = serviceFactory({
|
|
|
'authorized',
|
|
'authorized',
|
|
|
'unauthorized',
|
|
'unauthorized',
|
|
|
'error',
|
|
'error',
|
|
|
- ], null, this.onStateChange);
|
|
|
|
|
|
|
+ ], null, onStateChange);
|
|
|
this.syncState = serviceState([
|
|
this.syncState = serviceState([
|
|
|
'idle',
|
|
'idle',
|
|
|
'ready',
|
|
'ready',
|
|
|
'syncing',
|
|
'syncing',
|
|
|
'error',
|
|
'error',
|
|
|
- ], null, this.onStateChange);
|
|
|
|
|
|
|
+ ], null, onStateChange);
|
|
|
// this.initToken();
|
|
// this.initToken();
|
|
|
this.lastFetch = Promise.resolve();
|
|
this.lastFetch = Promise.resolve();
|
|
|
this.startSync = this.syncFactory();
|
|
this.startSync = this.syncFactory();
|
|
@@ -156,12 +163,6 @@ export const BaseService = serviceFactory({
|
|
|
this[key] = (...args) => { events[key](...args); };
|
|
this[key] = (...args) => { events[key](...args); };
|
|
|
});
|
|
});
|
|
|
},
|
|
},
|
|
|
- onStateChange() {
|
|
|
|
|
- browser.runtime.sendMessage({
|
|
|
|
|
- cmd: 'UpdateSync',
|
|
|
|
|
- data: getStates(),
|
|
|
|
|
- });
|
|
|
|
|
- },
|
|
|
|
|
log(...args) {
|
|
log(...args) {
|
|
|
console.log(...args); // eslint-disable-line no-console
|
|
console.log(...args); // eslint-disable-line no-console
|
|
|
},
|
|
},
|
|
@@ -232,7 +233,7 @@ export const BaseService = serviceFactory({
|
|
|
this.headers.Authorization = token ? `Bearer ${token}` : null;
|
|
this.headers.Authorization = token ? `Bearer ${token}` : null;
|
|
|
return !!token;
|
|
return !!token;
|
|
|
},
|
|
},
|
|
|
- request(options) {
|
|
|
|
|
|
|
+ loadData(options) {
|
|
|
const { progress } = this;
|
|
const { progress } = this;
|
|
|
let lastFetch;
|
|
let lastFetch;
|
|
|
if (options.delay == null) {
|
|
if (options.delay == null) {
|
|
@@ -253,23 +254,26 @@ export const BaseService = serviceFactory({
|
|
|
}
|
|
}
|
|
|
this.lastFetch = lastFetch;
|
|
this.lastFetch = lastFetch;
|
|
|
progress.total += 1;
|
|
progress.total += 1;
|
|
|
- this.onStateChange();
|
|
|
|
|
|
|
+ onStateChange();
|
|
|
return lastFetch.then(() => {
|
|
return lastFetch.then(() => {
|
|
|
let { prefix } = options;
|
|
let { prefix } = options;
|
|
|
if (prefix == null) prefix = this.urlPrefix;
|
|
if (prefix == null) prefix = this.urlPrefix;
|
|
|
const headers = Object.assign({}, this.headers, options.headers);
|
|
const headers = Object.assign({}, this.headers, options.headers);
|
|
|
- return request(prefix + options.url, {
|
|
|
|
|
|
|
+ let { url } = options;
|
|
|
|
|
+ if (url.startsWith('/')) url = prefix + url;
|
|
|
|
|
+ return request(url, {
|
|
|
headers,
|
|
headers,
|
|
|
method: options.method,
|
|
method: options.method,
|
|
|
body: options.body,
|
|
body: options.body,
|
|
|
- })
|
|
|
|
|
- .then(data => ({ data }), error => ({ error }))
|
|
|
|
|
- .then(({ data, error }) => {
|
|
|
|
|
- progress.finished += 1;
|
|
|
|
|
- this.onStateChange();
|
|
|
|
|
- if (error) return Promise.reject(error);
|
|
|
|
|
- return data;
|
|
|
|
|
|
|
+ responseType: options.responseType,
|
|
|
});
|
|
});
|
|
|
|
|
+ })
|
|
|
|
|
+ .then(({ data }) => ({ data }), error => ({ error }))
|
|
|
|
|
+ .then(({ data, error }) => {
|
|
|
|
|
+ progress.finished += 1;
|
|
|
|
|
+ onStateChange();
|
|
|
|
|
+ if (error) return Promise.reject(error);
|
|
|
|
|
+ return data;
|
|
|
});
|
|
});
|
|
|
},
|
|
},
|
|
|
sync() {
|
|
sync() {
|
|
@@ -399,7 +403,7 @@ export const BaseService = serviceFactory({
|
|
|
return Promise.all(promises);
|
|
return Promise.all(promises);
|
|
|
}));
|
|
}));
|
|
|
// ignore errors to ensure all promises are fulfilled
|
|
// ignore errors to ensure all promises are fulfilled
|
|
|
- return Promise.all(promiseQueue.map(promise => promise.catch(err => err || true)))
|
|
|
|
|
|
|
+ return Promise.all(promiseQueue.map(promise => promise.then(noop, err => err || true)))
|
|
|
.then(errors => errors.filter(Boolean))
|
|
.then(errors => errors.filter(Boolean))
|
|
|
.then(errors => { if (errors.length) throw errors; });
|
|
.then(errors => { if (errors.length) throw errors; });
|
|
|
})
|
|
})
|