diff --git a/CliClient/tests/test-utils.js b/CliClient/tests/test-utils.js index f393ff88e..f22923238 100644 --- a/CliClient/tests/test-utils.js +++ b/CliClient/tests/test-utils.js @@ -16,6 +16,7 @@ const { FileApiDriverMemory } = require('lib/file-api-driver-memory.js'); const { FileApiDriverLocal } = require('lib/file-api-driver-local.js'); const { FsDriverNode } = require('lib/fs-driver-node.js'); const { time } = require('lib/time-utils.js'); +const SyncTargetRegistry = require('lib/SyncTargetRegistry.js'); let databases_ = []; let synchronizers_ = []; @@ -119,8 +120,11 @@ async function setupDatabaseAndSynchronizer(id = null) { await setupDatabase(id); if (!synchronizers_[id]) { - synchronizers_[id] = new Synchronizer(db(id), fileApi(), Setting.value('appType')); - synchronizers_[id].setLogger(logger); + const SyncTargetClass = SyncTargetRegistry.classById(syncTargetId_); + const syncTarget = new SyncTargetClass(db(id)); + syncTarget.setFileApi(fileApi()); + syncTarget.setLogger(logger); + synchronizers_[id] = await syncTarget.synchronizer(); } if (syncTargetId_ == Setting.SYNC_TARGET_FILESYSTEM) { @@ -150,7 +154,6 @@ function fileApi() { fileApi_ = new FileApi(syncDir, new FileApiDriverLocal()); } else if (syncTargetId_ == Setting.SYNC_TARGET_MEMORY) { fileApi_ = new FileApi('/root', new FileApiDriverMemory()); - fileApi_.setLogger(logger); } // } else if (syncTargetId == Setting.SYNC_TARGET_ONEDRIVE) { // let auth = require('./onedrive-auth.json'); diff --git a/ReactNativeClient/lib/BaseSyncTarget.js b/ReactNativeClient/lib/BaseSyncTarget.js index ede9a4020..1d7ca225c 100644 --- a/ReactNativeClient/lib/BaseSyncTarget.js +++ b/ReactNativeClient/lib/BaseSyncTarget.js @@ -2,11 +2,16 @@ const { reg } = require('lib/registry.js'); class BaseSyncTarget { - constructor(db) { + constructor(db, options = null) { this.db_ = db; this.synchronizer_ = null; this.initState_ = null; this.logger_ = null; + this.options_ = options; + } + + option(name, defaultValue = null) { + return this.options_ && (name in this.options_) ? this.options_[name] : defaultValue; } logger() { @@ -37,6 +42,23 @@ class BaseSyncTarget { throw new Error('Not implemented'); } + initFileApi() { + throw new Error('Not implemented'); + } + + fileApi() { + if (this.fileApi_) return this.fileApi_; + this.fileApi_ = 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) + setFileApi(v) { + this.fileApi_ = v; + } + async synchronizer() { if (this.synchronizer_) return this.synchronizer_; @@ -79,4 +101,6 @@ class BaseSyncTarget { } +BaseSyncTarget.dispatch = (action) => {}; + module.exports = BaseSyncTarget; \ No newline at end of file diff --git a/ReactNativeClient/lib/SyncTarget1.js b/ReactNativeClient/lib/SyncTarget1.js index f451e3a91..da7f4a208 100644 --- a/ReactNativeClient/lib/SyncTarget1.js +++ b/ReactNativeClient/lib/SyncTarget1.js @@ -1,4 +1,9 @@ const BaseSyncTarget = require('lib/BaseSyncTarget.js'); +const { _ } = require('lib/locale.js'); +const { Setting } = require('lib/models/setting.js'); +const { FileApi } = require('lib/file-api.js'); +const { FileApiDriverMemory } = require('lib/file-api-driver-memory.js'); +const { Synchronizer } = require('lib/synchronizer.js'); class SyncTarget1 extends BaseSyncTarget { @@ -7,7 +12,7 @@ class SyncTarget1 extends BaseSyncTarget { } name() { - return 'Memory'; + return 'memory'; } label() { @@ -18,6 +23,17 @@ class SyncTarget1 extends BaseSyncTarget { return true; } + initFileApi() { + const fileApi = new FileApi('/root', new FileApiDriverMemory()); + fileApi.setLogger(this.logger()); + fileApi.setSyncTargetId(this.id()); + return fileApi; + } + + async initSynchronizer() { + return new Synchronizer(this.db(), this.fileApi(), Setting.value('appType')); + } + } module.exports = SyncTarget1; \ No newline at end of file diff --git a/ReactNativeClient/lib/SyncTarget2.js b/ReactNativeClient/lib/SyncTarget2.js new file mode 100644 index 000000000..8ed6bd806 --- /dev/null +++ b/ReactNativeClient/lib/SyncTarget2.js @@ -0,0 +1,39 @@ +const BaseSyncTarget = require('lib/BaseSyncTarget.js'); +const { _ } = require('lib/locale.js'); +const { Setting } = require('lib/models/setting.js'); +const { FileApi } = require('lib/file-api.js'); +const { FileApiDriverLocal } = require('lib/file-api-driver-local.js'); +const { Synchronizer } = require('lib/synchronizer.js'); + +class SyncTarget2 extends BaseSyncTarget { + + id() { + return 2; + } + + name() { + return 'filesystem'; + } + + label() { + return _('File system'); + } + + isAuthenticated() { + return true; + } + + initFileApi() { + const fileApi = new FileApi(Setting.value('sync.2.path'), new FileApiDriverLocal()); + fileApi.setLogger(this.logger()); + fileApi.setSyncTargetId(this.id()); + return fileApi; + } + + async initSynchronizer() { + return new Synchronizer(this.db(), this.fileApi(), Setting.value('appType')); + } + +} + +module.exports = SyncTarget2; \ No newline at end of file diff --git a/ReactNativeClient/lib/SyncTarget3.js b/ReactNativeClient/lib/SyncTarget3.js index 9e76dcd29..32fdbd655 100644 --- a/ReactNativeClient/lib/SyncTarget3.js +++ b/ReactNativeClient/lib/SyncTarget3.js @@ -9,8 +9,8 @@ const { FileApiDriverOneDrive } = require('lib/file-api-driver-onedrive.js'); class SyncTarget3 extends BaseSyncTarget { - constructor(db) { - super(); + constructor(db, options = null) { + super(db, options); this.api_ = null; } @@ -19,7 +19,7 @@ class SyncTarget3 extends BaseSyncTarget { } name() { - return 'OneDrive'; + return 'onedrive'; } label() { @@ -59,16 +59,18 @@ class SyncTarget3 extends BaseSyncTarget { return this.api_; } - async initSynchronizer() { - let fileApi = null; - - if (!this.api().auth()) throw new Error('User is not authentified'); - const appDir = await this.api().appDirectory(); - fileApi = new FileApi(appDir, new FileApiDriverOneDrive(this.api())); + initFileApi() { + const fileApi = new FileApi(appDir, new FileApiDriverOneDrive(this.api())); fileApi.setSyncTargetId(this.id()); fileApi.setLogger(this.logger()); + return fileApi; + } - return new Synchronizer(this.db(), fileApi, Setting.value('appType')); + async initSynchronizer() { + if (!this.isAuthenticated()) throw new Error('User is not authentified'); + + const appDir = await this.api().appDirectory(); + return new Synchronizer(this.db(), this.fileApi(), Setting.value('appType')); } } diff --git a/ReactNativeClient/lib/SyncTargetRegistry.js b/ReactNativeClient/lib/SyncTargetRegistry.js new file mode 100644 index 000000000..b6863be08 --- /dev/null +++ b/ReactNativeClient/lib/SyncTargetRegistry.js @@ -0,0 +1,16 @@ +const syncTargetClasses_ = { + 1: require('lib/SyncTarget1.js'), + 2: require('lib/SyncTarget2.js'), + 3: require('lib/SyncTarget3.js'), +}; + +class SyncTargetRegistry { + + static classById(syncTargetId) { + if (!syncTargetClasses_[syncTargetId]) throw new Error('Invalid id: ' + syncTargetId); + return syncTargetClasses_[syncTargetId]; + } + +} + +module.exports = SyncTargetRegistry; \ No newline at end of file diff --git a/ReactNativeClient/lib/registry.js b/ReactNativeClient/lib/registry.js index 4cab15e2d..c41f16430 100644 --- a/ReactNativeClient/lib/registry.js +++ b/ReactNativeClient/lib/registry.js @@ -8,18 +8,13 @@ const { FileApiDriverOneDrive } = require('lib/file-api-driver-onedrive.js'); const { shim } = require('lib/shim.js'); const { time } = require('lib/time-utils.js'); const { FileApiDriverMemory } = require('lib/file-api-driver-memory.js'); +const SyncTargetRegistry = require('lib/SyncTargetRegistry.js'); const { _ } = require('lib/locale.js'); const reg = {}; reg.initSynchronizerStates_ = {}; -reg.syncTargetClasses_ = { - 1: require('lib/SyncTarget1.js'), - // 2: require('lib/SyncTarget2.js'), - 3: require('lib/SyncTarget3.js'), -}; reg.syncTargets_ = {}; -//reg.synchronizers_ = {}; reg.logger = () => { if (!reg.logger_) { @@ -38,7 +33,7 @@ reg.syncTarget = (syncTargetId = null) => { if (syncTargetId === null) syncTargetId = Setting.value('sync.target'); if (reg.syncTargets_[syncTargetId]) return reg.syncTargets_[syncTargetId]; - const SyncTargetClass = reg.syncTargetClasses_[syncTargetId]; + const SyncTargetClass = SyncTargetRegistry.classById(syncTargetId); if (!reg.db()) throw new Error('Cannot initialize sync without a db'); const target = new SyncTargetClass(reg.db()); @@ -47,43 +42,6 @@ reg.syncTarget = (syncTargetId = null) => { return target; } -// reg.synchronizer = async (syncTargetId) => { -// if (reg.synchronizers_[syncTargetId]) return reg.synchronizers_[syncTargetId]; -// if (!reg.db()) throw new Error('Cannot initialize synchronizer: db not initialized'); - -// if (reg.initSynchronizerStates_[syncTargetId] == 'started') { -// // Synchronizer is already being initialized, so wait here till it's done. -// return new Promise((resolve, reject) => { -// const iid = setInterval(() => { -// if (reg.initSynchronizerStates_[syncTargetId] == 'ready') { -// clearInterval(iid); -// resolve(reg.synchronizers_[syncTargetId]); -// } -// if (reg.initSynchronizerStates_[syncTargetId] == 'error') { -// clearInterval(iid); -// reject(new Error('Could not initialise synchroniser')); -// } -// }, 1000); -// }); -// } else { -// reg.initSynchronizerStates_[syncTargetId] = 'started'; - -// try { -// const sync = await reg.initSynchronizer_(syncTargetId); -// reg.synchronizers_[syncTargetId] = sync; -// reg.initSynchronizerStates_[syncTargetId] = 'ready'; -// return sync; -// } catch (error) { -// reg.initSynchronizerStates_[syncTargetId] = 'error'; -// throw error; -// } -// } -// } - -// reg.syncHasAuth = (syncTargetId) => { -// return reg.syncTarget(syncTargetId).isAuthenticated(); -// } - reg.scheduleSync = async (delay = null) => { if (delay === null) delay = 1000 * 3; @@ -141,10 +99,6 @@ reg.scheduleSync = async (delay = null) => { } } -// reg.syncStarted = async () => { -// return reg.syncTarget().syncStarted(); -// } - reg.setupRecurrentSync = () => { if (reg.recurrentSyncId_) { shim.clearInterval(reg.recurrentSyncId_);