yjs/src/y.js
2015-11-30 15:56:45 +01:00

144 lines
3.4 KiB
JavaScript

/* @flow */
'use strict'
require('./Connector.js')(Y)
require('./Database.js')(Y)
require('./Transaction.js')(Y)
require('./Struct.js')(Y)
require('./Utils.js')(Y)
require('./Connectors/Test.js')(Y)
var requiringModules = {}
module.exports = Y
Y.extend = function (name, value) {
Y[name] = value
if (requiringModules[name] != null) {
requiringModules[name].resolve()
delete requiringModules[name]
}
}
Y.requestModules = requestModules
function requestModules (modules) {
var promises = []
for (var i = 0; i < modules.length; i++) {
var modulename = 'y-' + modules[i].toLowerCase()
if (Y[modules[i]] == null) {
if (requiringModules[modules[i]] == null) {
try {
require(modulename)(Y)
} catch (e) {
// module does not exist
if (typeof window !== 'undefined') {
var imported = document.createElement('script')
imported.src = Y.sourceDir + '/' + modulename + '/' + modulename + '.js'
document.head.appendChild(imported)
let requireModule = {}
requiringModules[modules[i]] = requireModule
requireModule.promise = new Promise(function (resolve) {
requireModule.resolve = resolve
})
promises.push(requireModule.promise)
} else {
throw e
}
}
} else {
promises.push(requiringModules[modules[i]].promise)
}
}
}
return Promise.all(promises)
}
require('./Types/Map.js')(Y)
/* ::
type MemoryOptions = {
name: 'memory'
}
type IndexedDBOptions = {
name: 'indexeddb',
namespace: string
}
type DbOptions = MemoryOptions | IndexedDBOptions
type WebRTCOptions = {
name: 'webrtc',
room: string
}
type WebsocketsClientOptions = {
name: 'websockets-client',
room: string
}
type ConnectionOptions = WebRTCOptions | WebsocketsClientOptions
type TypesOptions = Array<'array'|'map'|'text'>
type YOptions = {
connector: ConnectionOptions,
db: DbOptions,
types: TypesOptions,
sourceDir: string
}
*/
function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
opts.types = opts.types != null ? opts.types : []
var modules = [opts.db.name, opts.connector.name].concat(opts.types)
Y.sourceDir = opts.sourceDir
return Y.requestModules(modules).then(function () {
return new Promise(function (resolve) {
var yconfig = new YConfig(opts, function () {
yconfig.db.whenUserIdSet(function () {
resolve(yconfig)
})
})
})
})
}
class YConfig {
/* ::
db: Y.AbstractDatabase;
connector: Y.AbstractConnector;
*/
constructor (opts, callback) {
this.db = new Y[opts.db.name](this, opts.db)
this.connector = new Y[opts.connector.name](this, opts.connector)
this.db.requestTransaction(function * requestTransaction () {
// create initial Map type
this.store._temporaryUserIdGenerator = function () {
return ['_', 0]
}
var typeid = yield* Y.Map.createType.call(this)
var type = yield* this.getType(typeid)
this.store.y.root = type
this.store._temporaryUserIdGenerator = null
setTimeout(callback, 0)
})
}
isConnected () {
return this.connector.isSynced
}
disconnect () {
return this.connector.disconnect()
}
reconnect () {
return this.connector.reconnect()
}
destroy () {
this.disconnect()
this.db.destroy()
this.connector = null
this.db = null
}
}
if (typeof window !== 'undefined') {
window.Y = Y
}