diff --git a/tracker/tracker-mobx/README.md b/tracker/tracker-mobx/README.md index 73fb021cf..3011a1395 100644 --- a/tracker/tracker-mobx/README.md +++ b/tracker/tracker-mobx/README.md @@ -13,75 +13,31 @@ Then put the generated middleware into your Redux chain. ```js import Tracker from '@openreplay/tracker'; import trackerMobX from '@openreplay/tracker-mobx'; +import { observe } from 'mobx'; const tracker = new Tracker({ projectKey: YOUR_PROJECT_KEY, }); -tracker.plugin(trackerMobX()); +const mobxTrackerInstance = tracker.use(trackerMobX(options)); // look below for available options +observe(yourMobxStore, mobxTrackerInstance) ``` -This plugin is inspired by [mobx-logger](https://github.com/winterbe/mobx-logger), hence it has similar configurations. - -The default configurations are following +Options: ```js +interface Options { + predicate?: (ev: { type: string; name: string; object: any; debugObjectName: string }) => boolean; + sanitize?: (ev: { state: any; type: string; property: string }) => { state: any; type: string; property: string }; + update?: boolean; + add?: boolean; + delete?: boolean; +} + trackerMobX({ predicate: () => true, - action: true, - reaction: true, - transaction: true, - compute: true + sanitize: (event) => event }) ``` -You can disable logging for actions and computed properties by providing a static `trackerMobXConfig`. This is useful to protect the private user data and keep your logs clean. - -Here's an example of how to disable logging for all actions and computed properties for a given class: - -```js -class MyModel { - static trackerMobXConfig: { - enabled: false - }; - - // ... -} -``` - -Alternatively you can disable logging for particular class methods: - -```js -class MyStore { - static trackerMobXConfig: { - methods: { - myAction: false - } - }; - - @action myAction() { - // calls to this method won't be logged - } -} -``` - -You can combine the above examples to whitelist certain actions for being logged: - -```js -class MyStore { - static trackerMobXConfig: { - enabled: false, - methods: { - myAction: true - } - }; - - @action myAction() { - // only calls to this method are being logged - } - - // other methods won't be logged ... -} -``` - -> Please keep in mind that at this point `trackerMobXConfig` is only available for actions (`@action`) and computed properties (`@computed`). +Where `predicate` can be used to dynamically turn off capturing and `sanitize` can be used to modify the payload before sending it to backend. diff --git a/tracker/tracker-mobx/package.json b/tracker/tracker-mobx/package.json index 6a66071c8..a068278e3 100644 --- a/tracker/tracker-mobx/package.json +++ b/tracker/tracker-mobx/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker-mobx", "description": "Tracker plugin for MobX events recording", - "version": "3.0.1", + "version": "4.0.0", "keywords": [ "mobx", "logging", @@ -23,12 +23,10 @@ }, "dependencies": {}, "peerDependencies": { - "@openreplay/tracker": ">=3.0.0", - "mobx": "^4.15.7" + "@openreplay/tracker": ">=3.0.0" }, "devDependencies": { "@openreplay/tracker": "file:../tracker", - "mobx": "^4.15.7", "prettier": "^1.18.2", "replace-in-files-cli": "^1.0.0", "typescript": "^3.6.4" diff --git a/tracker/tracker-mobx/src/index.ts b/tracker/tracker-mobx/src/index.ts index e81d42cff..6689cbf89 100644 --- a/tracker/tracker-mobx/src/index.ts +++ b/tracker/tracker-mobx/src/index.ts @@ -1,25 +1,24 @@ -import { spy } from 'mobx'; import { App, Messages } from '@openreplay/tracker'; -import log from './log'; -import { Encoder, sha1 } from './syncod'; +import log from './log.js'; +import { Encoder, sha1 } from './syncod/index.js'; export interface Options { - predicate: (ev: any) => boolean, - action: boolean; - reaction: boolean; - transaction: boolean; - compute: boolean; + predicate: (ev: { type: string; name: string; object: any; debugObjectName: string }) => boolean; + sanitize: (ev: { state: any; type: string; property: string }) => { state: any; type: string; property: string }; + update: boolean; + delete: boolean; + add: boolean; } -export default function(opts: Partial = {}) { +export default function (opts: Partial = {}) { const options: Options = Object.assign( { predicate: () => true, - action: true, - reaction: true, - transaction: true, - compute: true, + sanitize: (ev) => ev, + update: true, + delete: true, + add: true, }, opts, ); @@ -28,20 +27,23 @@ export default function(opts: Partial = {}) { return; } const encoder = new Encoder(sha1, 50); - spy(app.safe(ev => { - if (!options.predicate(ev)) return; - const { type } = ev; - ev = options[type] && log[type] && log[type](ev); - if (!ev) return; - if (typeof ev.name === 'string' && ev.name) { - app.send(Messages.StateAction(ev.name)); - } - const payload = encoder.encode(ev); - const table = encoder.commit(); - for (let key in table) app.send(Messages.OTable(key, table[key])); - app.send(Messages.MobX(type, payload)); - }), - ); + return (ev: { type: string; name: string; object: any; debugObjectName: string }) => { + if (!options.predicate(ev)) return; + const { type } = ev; + const event = options[type] && log[type] && log[type](ev); + if (!event) return; + const sanitizedEvent = options.sanitize(event); + const evType = ev.debugObjectName?.split('@')[0] || ev.type; + if (evType) { + app.send(Messages.StateAction(evType)); + } + + const payload = encoder.encode(sanitizedEvent); + const table = encoder.commit(); + + for (let key in table) app.send(Messages.OTable(key, table[key])); + app.send(Messages.MobX(evType, payload)); + } }; } diff --git a/tracker/tracker-mobx/src/log.ts b/tracker/tracker-mobx/src/log.ts index 4f6cc0560..d21d2fc95 100644 --- a/tracker/tracker-mobx/src/log.ts +++ b/tracker/tracker-mobx/src/log.ts @@ -1,4 +1,5 @@ // Based on https://github.com/winterbe/mobx-logger/blob/master/src/log.js +// though it is not used anymore due to spy() being no op in production interface TrackerMobXConfig { enabled?: boolean; @@ -36,13 +37,6 @@ const getPropName = ev => { ); }; -const action = ev => { - if (!isLoggingEnabled(ev)) { - return; - } - - return { name: ev.name, arguments: ev.arguments, object: ev.object }; -}; const reaction = ev => { const name = ev.name.replace('#null', ''); @@ -65,4 +59,30 @@ const compute = ev => { return { name }; }; -export default { action, reaction, transaction, compute }; + +const observeAction = ev => { + return { + state: ev.object, + type: ev.type, + property: ev.name, + } +} + +const action = ev => { + if (!isLoggingEnabled(ev)) { + return; + } + + return { name: ev.name, arguments: ev.arguments, object: ev.object }; +}; + + +export default { + // action, + // reaction, + // transaction, + // compute, + update: observeAction, + delete: observeAction, + add: observeAction +};