{EventEmitter} = require 'events' formats = require './formats' getOplogStream = require './getOplogStream' {walk, convertObjectID} = require './util' applyDefaults = (options) -> options or= {} options.port or= 27017 options.host or= 'localhost' options.authdb or= 'admin' options.replicaSet or= null options.dbOpts or= {w: 1} options.format or= 'raw' options.useMasterOplog or= false options.convertObjectIDs ?= true options.onError or= (error) -> console.log 'Error - MongoWatch:', (error?.stack or error) options.onDebug or= -> #options.username or= null #options.password or= null return options class MongoWatch status: 'connecting' watching: [] constructor: (options) -> @options = applyDefaults options @channel = new EventEmitter @channel.on 'error', @options.onError @channel.on 'connected', => @status = 'connected' @debug = @options.onDebug getOplogStream @options, (err, @stream, @oplogClient) => @channel.emit 'error', err if err @debug "Emiting 'connected'. Stream exists:", @stream? @channel.emit 'connected' ready: (done) -> isReady = @status is 'connected' @debug 'Ready:', isReady if isReady return done() else @channel.once 'connected', done watch: (collection, notify) -> collection ||= 'all' notify ||= console.log @ready => unless @watching[collection]? watcher = (data) => relevant = (collection is 'all') or (data.ns is collection) @debug 'Data changed:', {data: data, watching: collection, relevant: relevant} return unless relevant channel = if collection then "change:#{collection}" else 'change' formatter = formats[@options.format] or formats['raw'] event = formatter data # convert ObjectIDs to strings if @options.convertObjectIDs is true event = walk event, convertObjectID @debug 'Emitting event:', {channel: channel, event: event} @channel.emit collection, event # watch user model @debug 'Adding emitter for:', {collection: collection} @stream.on 'data', watcher @watching[collection] = watcher @debug 'Adding listener on:', {collection: collection} @channel.on collection, notify stop: (collection) -> @debug 'Removing listeners for:', collection collection ||= 'all' @channel.removeAllListeners collection @stream.removeListener 'data', @watching[collection] delete @watching[collection] stopAll: -> @stop coll for coll of @watching module.exports = MongoWatch