diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9e32b41 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# editorconfig.org +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/README.md b/README.md index d3557fe..b5702be 100644 --- a/README.md +++ b/README.md @@ -24,15 +24,12 @@ $ gulp watch ```coffeescript EventLog = require('resin-event-log') -PinejsClient = require('pinejs-client') -pinejsClientInstance = new PinejsClient(...) - -eventLogger = EventLog pinejsClientInstance, 'Subsystem - UI, CLI, etc.', { +eventLogger = EventLog MIXPANEL_TOKEN, 'Subsystem - UI, CLI, etc.', { # Hooks: - beforeCreate: -> - @start('User ID', 'Interaction ID') # If no Interaction ID provided, it's auto-generated - afterCreate: (type) -> + beforeCreate: (type, jsonData, applicationId, deviceId, callback) -> + @start('User ID', callback) + afterCreate: (type, jsonData, applicationId, deviceId) -> if type is 'User Logout' @end() } @@ -51,10 +48,6 @@ eventLoger.user.login() ## Available hooks: ```coffeescript -beforeStart = (userId, interactionUuid) -> -afterStart = (userId, interactionUuid) -> -beforeEnd = -> -afterEnd = -> -beforeCreate = (type, jsonData, applicationId, deviceId) -> -afterCreate = (type, jsonData, applicationId, deviceId) -> +beforeCreate = (type, jsonData, applicationId, deviceId, callback) -> callback() +afterCreate = (type, jsonData, applicationId, deviceId) -> # ``` \ No newline at end of file diff --git a/bin/resin-event-log.js b/bin/resin-event-log.js index 7bea01d..1b3671c 100644 --- a/bin/resin-event-log.js +++ b/bin/resin-event-log.js @@ -1,11 +1,11 @@ (function() { (function(root, factory) { if (typeof define === 'function' && define.amd) { - return define(['lodash', '../bower_components/node-uuid/uuid'], factory); + return define(['../bower_components/resin-mixpanel-client/bin/resin-mixpanel-client', 'lodash'], factory); } else if (typeof exports === 'object') { - return module.exports = factory(require('lodash'), require('node-uuid')); + return module.exports = factory(require('./resin-mixpanel-client'), require('lodash')); } - })(this, function(_, uuid) { + })(this, function(ResinMixpanelClient, _) { var EVENTS, HOOKS; EVENTS = { user: ['login', 'logout', 'signup', 'passwordCreate', 'passwordEdit', 'emailEdit'], @@ -16,53 +16,61 @@ deviceEnvironmentVariable: ['create', 'edit', 'delete'] }; HOOKS = { - beforeStart: function(userId, interactionUuid) {}, - afterStart: function(userId, interactionUuid) {}, - beforeEnd: function() {}, - afterEnd: function() {}, - beforeCreate: function(type, jsonData, applicationId, deviceId) {}, + beforeCreate: function(type, jsonData, applicationId, deviceId, callback) { + return callback(); + }, afterCreate: function(type, jsonData, applicationId, deviceId) {} }; - return function(PinejsClient, subsystem, hooks) { - var exported; - if (!subsystem) { - throw Error('subsystem is required to start events interaction.'); + return function(mixpanelToken, subsystem, hooks) { + var exported, getMixpanelUser, mixpanel; + if (!mixpanelToken || !subsystem) { + throw Error('mixpanelToken and subsystem are required to start events interaction.'); } hooks = _.merge(HOOKS, hooks); + mixpanel = ResinMixpanelClient(mixpanelToken); + getMixpanelUser = function(userData) { + var mixpanelUser; + mixpanelUser = _.extend({ + '$email': userData.email, + '$name': userData.username + }, userData); + return _.pick(mixpanelUser, ['$email', '$name', '$created', 'hasPasswordSet', 'iat', 'id', 'permissions', 'public_key', 'username']); + }; exported = { subsystem: subsystem, - start: function(userId, interactionUuid) { - hooks.beforeStart.apply(this, arguments); - if (!userId) { - throw Error('userId is required to start events interaction.'); + start: function(user, callback) { + var login, mixpanelUser; + if (!user) { + throw Error('user is required to start events interaction.'); + } + this.userId = user.id; + mixpanelUser = getMixpanelUser(user); + login = function() { + return mixpanel.login(user.username, function() { + return mixpanel.setUserOnce(mixpanelUser, callback); + }); + }; + if (mixpanelUser.$created) { + return mixpanel.signup(user.username, function() { + return login(); + }); } - this.userId = userId; - this.interactionUuid = interactionUuid || uuid(); - return hooks.afterStart.call(this, this.userId, this.interactionUuid); + return login(); }, - end: function() { - hooks.beforeEnd.apply(this); + end: function(callback) { this.userId = null; - this.interactionUuid = null; - return hooks.afterEnd.apply(this); + return mixpanel.logout(callback); }, create: function(type, jsonData, applicationId, deviceId) { - var args; - args = arguments; - hooks.beforeCreate.apply(this, args); - return PinejsClient.post({ - resource: 'event', - body: { - user: this.userId, - interaction_uuid: this.interactionUuid, - application_id: applicationId, - device_id: deviceId, - type: "[" + this.subsystem + "] " + type, - json_data: jsonData - } - }).then((function(_this) { + return hooks.beforeCreate.call(this, type, jsonData, applicationId, deviceId, (function(_this) { return function() { - return hooks.afterCreate.apply(_this, args); + return mixpanel.track("[" + _this.subsystem + "] " + type, { + applicationId: applicationId, + deviceId: deviceId, + jsonData: jsonData + }, function() { + return hooks.afterCreate.call(_this, type, jsonData, applicationId, deviceId); + }); }; })(this)); } diff --git a/bower.json b/bower.json index 90f7578..0e62cc1 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "resin-event-log", "main": "bin/resin-event-log.js", - "version": "0.0.3", + "version": "0.0.4", "authors": [ "Iskren Slavov " ], @@ -15,6 +15,7 @@ ], "dependencies": { "lodash": "~3.*.*", - "node-uuid": "~1.*.*" + "node-uuid": "~1.*.*", + "resin-mixpanel-client": "~0.0.2" } } diff --git a/package.json b/package.json index 7e637eb..e66b9a5 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "resin-event-log", - "version": "0.0.3", + "version": "0.0.4", "description": "", "main": "bin/resin-event-log.js", "dependencies": { "lodash": "^3.*.*", - "node-uuid": "^1.*.*" + "resin-mixpanel-client": "^0.0.2" }, "devDependencies": { "coffee-script": "^1.9.3", diff --git a/src/resin-event-log.coffee b/src/resin-event-log.coffee index 5feb433..511c093 100644 --- a/src/resin-event-log.coffee +++ b/src/resin-event-log.coffee @@ -1,13 +1,19 @@ ((root, factory) -> if typeof define is 'function' and define.amd # AMD. Register as an anonymous module. - define ['lodash', '../bower_components/node-uuid/uuid'], factory + define [ + '../bower_components/resin-mixpanel-client/bin/resin-mixpanel-client' + 'lodash' + ], factory else if typeof exports is 'object' # Node. Does not work with strict CommonJS, but # only CommonJS-like enviroments that support module.exports, # like Node. - module.exports = factory(require('lodash'), require('node-uuid')) -) this, (_, uuid) -> + module.exports = factory( + require('./resin-mixpanel-client') + require('lodash') + ) +) this, (ResinMixpanelClient, _) -> EVENTS = user: [ 'login' @@ -46,52 +52,64 @@ ] HOOKS = - beforeStart: (userId, interactionUuid) -> # - afterStart: (userId, interactionUuid) -> # - beforeEnd: -> # - afterEnd: -> # - beforeCreate: (type, jsonData, applicationId, deviceId) -> # + beforeCreate: (type, jsonData, applicationId, deviceId, callback) -> callback() afterCreate: (type, jsonData, applicationId, deviceId) -> # - return (PinejsClient, subsystem, hooks) -> - if not subsystem - throw Error('subsystem is required to start events interaction.') + return (mixpanelToken, subsystem, hooks) -> + if not mixpanelToken or not subsystem + throw Error('mixpanelToken and subsystem are required to start events interaction.') hooks = _.merge(HOOKS, hooks) + mixpanel = ResinMixpanelClient(mixpanelToken) + + getMixpanelUser = (userData) -> + mixpanelUser = _.extend + '$email': userData.email + '$name': userData.username + , userData + + return _.pick mixpanelUser, [ + '$email' + '$name' + '$created' + 'hasPasswordSet' + 'iat' + 'id' + 'permissions' + 'public_key' + 'username' + ] exported = subsystem: subsystem - start: (userId, interactionUuid) -> - hooks.beforeStart.apply(this, arguments) - if not userId - throw Error('userId is required to start events interaction.') + start: (user, callback) -> + if not user + throw Error('user is required to start events interaction.') - @userId = userId - @interactionUuid = interactionUuid or uuid() - hooks.afterStart.call(this, @userId, @interactionUuid) + @userId = user.id + mixpanelUser = getMixpanelUser(user) - end: -> - hooks.beforeEnd.apply(this) + login = -> + mixpanel.login user.username, -> + mixpanel.setUserOnce(mixpanelUser, callback) + if (mixpanelUser.$created) + return mixpanel.signup user.username, -> + login() + login() + + end: (callback) -> @userId = null - @interactionUuid = null - hooks.afterEnd.apply(this) + mixpanel.logout(callback) create: (type, jsonData, applicationId, deviceId) -> - args = arguments - - hooks.beforeCreate.apply(this, args) - PinejsClient.post - resource: 'event' - body: - user: @userId - interaction_uuid: @interactionUuid - application_id: applicationId - device_id: deviceId - type: "[#{@subsystem}] #{type}" - json_data: jsonData - .then => - hooks.afterCreate.apply(this, args) + hooks.beforeCreate.call this, type, jsonData, applicationId, deviceId, => + mixpanel.track "[#{@subsystem}] #{type}", { + applicationId + deviceId + jsonData + }, => + hooks.afterCreate.call(this, type, jsonData, applicationId, deviceId) _.forEach EVENTS, (events, base) ->