1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00
joplin/packages/lib/BaseSyncTarget.ts

154 lines
4.0 KiB
TypeScript

import Logger from '@joplin/utils/Logger';
import Synchronizer from './Synchronizer';
import EncryptionService from './services/e2ee/EncryptionService';
import shim from './shim';
import ResourceService from './services/ResourceService';
import ShareService from './services/share/ShareService';
export default class BaseSyncTarget {
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
public static dispatch: Function = () => {};
private synchronizer_: Synchronizer = null;
private initState_: any = null;
private logger_: Logger = null;
private options_: any;
private db_: any;
protected fileApi_: any;
public constructor(db: any, options: any = null) {
this.db_ = db;
this.options_ = options;
}
public static supportsConfigCheck() {
return false;
}
// Returns true if the sync target expects a non-empty sync.{id}.password
// setting.
public static requiresPassword() {
return false;
}
public static description(): string {
return '';
}
public static supportsSelfHosted(): boolean {
return true;
}
public static supportsRecursiveLinkedNotes(): boolean {
return false;
}
public option(name: string, defaultValue: any = null) {
return this.options_ && name in this.options_ ? this.options_[name] : defaultValue;
}
protected logger() {
return this.logger_;
}
public setLogger(v: Logger) {
this.logger_ = v;
}
protected db() {
return this.db_;
}
// If [] is returned it means all platforms are supported
public static unsupportedPlatforms(): any[] {
return [];
}
public async isAuthenticated() {
return false;
}
public authRouteName(): string {
return null;
}
public static id() {
throw new Error('id() not implemented');
}
// Note: it cannot be called just "name()" because that's a reserved keyword and
// it would throw an obscure error in React Native.
public static targetName() {
throw new Error('targetName() not implemented');
}
public static label() {
throw new Error('label() not implemented');
}
protected async initSynchronizer(): Promise<Synchronizer> {
throw new Error('initSynchronizer() not implemented');
}
protected async initFileApi(): Promise<any> {
throw new Error('initFileApi() not implemented');
}
public async fileApi() {
if (this.fileApi_) return this.fileApi_;
this.fileApi_ = await this.initFileApi();
return this.fileApi_;
}
// Usually each sync target should create and setup its own file API via initFileApi()
// but for testing purposes it might be convenient to provide it here so that multiple
// clients can share and sync to the same file api (see test-utils.js)
public setFileApi(v: any) {
this.fileApi_ = v;
}
public async synchronizer(): Promise<Synchronizer> {
if (this.synchronizer_) return this.synchronizer_;
if (this.initState_ === 'started') {
// Synchronizer is already being initialized, so wait here till it's done.
return new Promise((resolve, reject) => {
const iid = shim.setInterval(() => {
if (this.initState_ === 'ready') {
shim.clearInterval(iid);
resolve(this.synchronizer_);
}
if (this.initState_ === 'error') {
shim.clearInterval(iid);
reject(new Error('Could not initialise synchroniser'));
}
}, 1000);
});
} else {
this.initState_ = 'started';
try {
this.synchronizer_ = await this.initSynchronizer();
this.synchronizer_.setLogger(this.logger());
this.synchronizer_.setEncryptionService(EncryptionService.instance());
this.synchronizer_.setResourceService(ResourceService.instance());
this.synchronizer_.setShareService(ShareService.instance());
this.synchronizer_.dispatch = BaseSyncTarget.dispatch;
this.initState_ = 'ready';
return this.synchronizer_;
} catch (error) {
this.initState_ = 'error';
throw error;
}
}
}
public async syncStarted() {
if (!this.synchronizer_) return false;
if (!(await this.isAuthenticated())) return false;
const sync = await this.synchronizer();
return sync.state() !== 'idle';
}
}