hotplate.hotEvents.onCollect( 'stores', 'hotCoreStoreLogger', hotplate.cacheable( function( done ){

  hotCoreStore.get( function( err, s ){
    if( err ) return done( err );

    var BasicDbStore = s.BasicDbStore;
    var BasicSchema = s.BasicSchema;

    var Log = declare( [ BasicDbStore ], {
      schema: new BasicSchema({

        logLevel   : { type: 'number', required: true, default: 1 },
        error      : { type: 'serialize', required: false },
        errorName  : { type: 'string', required: false },
        errorMessage: { type: 'string', required: false },
        errorStack : { type: 'string', required: false },
        errors     : { type: 'serialize', required: false },
        message    : { type: 'string', required: false },
        data       : { type: 'serialize', required: false },
        loggedOn   : { type: 'date', required: true, default: function(){ return new Date() } },
        workspaceId: { type: 'id' },
        userId     : { type: 'id', required: false },
        system     : { type: 'boolean', required: true, defaule: false },
      }),
      storeName:  'log',
      paramIds: [ 'id' ],
    });
    stores.log = new Log();

    done( null, stores );
  });

}));
Example #2
0
hotplate.hotEvents.onCollect('stores', 'hotCoreComet', hotplate.cacheable(function (done) {
  // This module only uses JsonRestStores as a way to access the DB and expose methods,
  // it doesn't mixin with hotJsonRestStores (which would do Comet event emission etc.)

  hotCoreStore.get(function (err, s) {
    if (err) return done(err)

    var BasicDbStore = s.BasicDbStore
    var BasicSchema = s.BasicSchema

    var HotStore = s.HotStore
    var HotSchema = s.HotSchema

    // ***********************************
    // *** OPEN TABS   *******************
    // ***********************************

    var Tabs = declare(HotStore, {

      schema: new BasicSchema({
        id: { type: 'string', searchable: true, unique: true },
        lastSync: { type: 'date', searchable: true, default: function () { return new Date() } }
      }),

      handlePost: true,
      handleDelete: true,

      storeName: 'tabs',
      paramIds: [ 'id' ]

      /*
      nested: [
        {
          type: 'multiple',
          store: 'tabMessages',
          join: { tabId: 'tabId'},
        },
      ]
      */

    })
    stores.tabs = new Tabs()

    // Internal store, only used via API
    var TabMessages = declare(BasicDbStore, {

      schema: new BasicSchema({
        message: { type: 'serialize', required: true },
        added: { type: 'date', searchable: true, protected: true, default: function () { return new Date() } },
        tabId: { type: 'string', searchable: true, required: true }
      }),

      paramIds: [ 'id' ],
      storeName: 'tabMessages',

      autoLookup: {
        tabId: 'tabs'
      },

      sortableFields: [ 'added' ],
      defaultSort: { added: 1 }
    })
    stores.tabMessages = new TabMessages()

    // Internal store, only used via API
    var TabSubscriptions = declare(BasicDbStore, {

      schema: new BasicSchema({
        added: { type: 'date', protected: true, searchable: true, default: function () { return new Date() } },
        tabId: { type: 'string', searchable: true, required: true },
        handle: { type: 'string', searchable: true, required: true, trim: 255 },
        p1: { type: 'string', searchable: true, required: false, trim: 1024 },
        p2: { type: 'string', searchable: true, required: false, trim: 1024 },
        p3: { type: 'string', searchable: true, required: false, trim: 1024 },
        p4: { type: 'string', searchable: true, required: false, trim: 1024 },
        hash: { type: 'string', searchable: true, required: false, trim: 1024 }
      }),

      paramIds: [ 'id' ],
      storeName: 'tabSubscriptions'

    })
    stores.tabSubscriptions = new TabSubscriptions()

    // FINISHED
    var UserOnline = declare([JsonRestStores, JsonRestStores.HTTPMixin], {
      schema: new HotSchema({

        userId: {
          type: 'id'
        }

      }),

      handleGet: true,

      storeName: 'userOnline',

      publicURL: '/userOnline/:userId',
      hotExpose: true,

      implementFetchOne: function (request, cb) {
        consolelog('*************************Checking online status of:', request.params.userId)
        consolelog('Connections:', connections)
        for (var k in connections) {
          var $c = connections[ k ]

          consolelog('CHECKING: ', request.params.userId, $c.userId, $c.loggedIn, $c.ws && $c.ws.readyState)
          if ($c && $c.userId && $c.loggedIn && request.params.userId.toString() === $c.userId.toString() && $c.ws && $c.ws.readyState === 1) {
            consolelog('Returning YES!')
            return cb(null, { online: true })
          }
        }
        consolelog('Returning NO!')
        return cb(null, { online: false })
      }

    })
    stores.userOnline = new UserOnline()

    done(null, stores)
  })
}))
Example #3
0
hotplate.hotEvents.onCollect('setRoutes', 'hotCoreComet', function (app, done) {
  hotCoreStore.get(function (err, s) {
    if (err) return done(err)

    Object.keys(s.HotStore.registry).forEach((k) => {
      var store = s.HotStore.registry[ k ]

      if ((store.emitCometDbEvents) && store.dbLayer) {
        [ 'simpledblayer-update-one', 'simpledblayer-delete-one', 'simpledblayer-insert' ].forEach((op) => {
          consolelog('Adding listener for', store.storeName, 'for op:', op)
          store.dbLayer.onCollect(op, function (info, cb) {
            var k

            consolelog('SPROUT: DB OP ', op, 'WILL GENERATE A COMET EVENT. INFO:', require('util').inspect(info, { dpeth: 1 }))

            // WAIT. If the query was initiated within JsonRestStores, and the store is also store-aware,
            // will stop here since stores with both emitCometStoreEvents and emitCometDbEvents will
            // generate TWO events per REST call
            if (info.options.fromJsonRestStores && store.emitCometStoreEvents) {
              consolelog('Quitting, since this DB query came from JsonRestStores, and this store ALREADY has emitCometStoreEvents on')
              return cb(null)
            }

            // Suppress comet messages
            if (info.options.noComet) {
              consolelog('Quitting, since noComet is on')
              return cb(null)
            }

            // TEMPORARY
            // if( ! info.options.request ){
            //  console.log("WARNING: REQUEST NOT PASSED IN OPTION", info );
            // }

            // console.log("OPTION REQUEST:", info.options.request );
            var request = info.options.request || {}
            var sessionData = request.session || {}

            // Make a new request object that is a mere approximation of a "real"
            // JsonRestStores request object, borrowing as much as possible from
            // the "original" one.
            var newRequest = {}
            for (k in request) {
              newRequest[ k ] = request[ k ]
            }
            newRequest.body = info.record
            newRequest.params = []
            newRequest.data = []

            for (k in request.data) {
              newRequest.data[ k ] = request.data
            }

            newRequest.data.doc = info.recordBefore
            newRequest.data.fullDoc = info.recordBefore
            newRequest.data.docAfter = info.record
            newRequest.data.fullDocAfter = info.record
            newRequest.fromDbComet = true

            var method = {
              'simpledblayer-update-one': 'put',
              'simpledblayer-delete-one': 'delete',
              'simpledblayer-insert': 'post'
            }[op]

            store.prepareBeforeSendProxy(newRequest, method, info.record, function (err, preparedDoc) {
              if (err) {
                logger.log({ error: err, system: true, logLevel: 3, message: 'Error preparing doc using prepareBeforeSendProxy' })
                cb(null)
              }

              consolelog("Session data from db's 'request' option:", sessionData)

              /*
              stores.tabs.dbLayer.select( { }, function( err, tabs ){
                if( err ){
                  logger.log( { error: err, system: true, logLevel: 3, message: "Error selecting tabs from db" } );
                  cb( null );
                }
              */

              var message = {
                type: 'store-change',
                op: method,
                record: info.record,
                storeName: store.storeName,
                fromDb: true
              }
              if (op === 'simpledblayer-update-one') message.existing = true
              if (op === 'simpledblayer-insert') message.new = true

                // This will only work if the store was enriched with the
                // Comet mixin _and_ the client sent the tabId
              if (request.data && request.data.fromTabId) {
                var fromTabId = request.data.fromTabId
                consolelog('Store is comet-emabled, it will also have a fromTabId:', fromTabId)
              }

              var cometEvent = {
                message: message,
                sessionData: sessionData,
                fromClient: false,
                fromTabId: fromTabId,
                store: store
              }

              var ce = cometEvent
              consolelog('Comet event: ', { message: ce.message, sessionData: ce.sessionData, connections: ce.connections, tabs: ce.tabs })

                // The message doesn't have tabId, since... it can't.
              emitAndSendMessages(cometEvent, function (err) {
                if (err) consolelog('Error runnign emitAndSendMessages:', err)

                cb(null)
              })
              // });
            })
          })
        })
      }
    })

    // All listeners are set!
    done(null)
  })
})