Can you trigger code on a State Transition?


#1

Is there a hook middleware or some other place where I can detect a State transition and execute code? Want to be able to detect fromState and toState

My idea right now is to do a hook on the before.response middleware and store the current state in a session variable: jovo.$session.$data.MYSTATE. If this value and jovo.getState() are different, then I know a state change has occurred. The fromState would be MYSTATE and the toState would be the value from getState. I could do conditionals to check for specific transitions and execute code.

Is there a better approach?

What is the earliest standard, before or after middleware that I can plug into for this?

@AlexSwe Any recommendations?


#2

Hey @marktucker

I would recommend using the jovo object context. Storing MYSTATE in the session wouldn’t be necessary here.

Example:

app.hook('after.platform.init', (error, host, jovo) => {
   jovo.$data.oldState = jovo.getState();
});

app.hook('before.response', (error, host, jovo) => {
    if (jovo.$data.oldState !== jovo.getState()) {
        console.log('state transition')
    }
});

#3

Thinking through this some more, I may actually need to know the State transition before I get to the response. For example, at the moment that I call one of the following, I would like to have a middleware to know the fromState and toState:

  • followUpState
  • removeState
  • toStateIntent

Thinking of a situation where I am handling a request and the STATE is set already and now I call removeState and I want some code to execute before I continue with the line after removeState. There might be values that I want to set (or remove) in session as soon as a transition into and out of a state occurs and I want the code to run before any other code runs.


#4

You can do it by modifying the prototype of the Jovo class

const {Jovo} = require('jovo-core');

const oldToStateIntent = Jovo.prototype.toStateIntent;
Jovo.prototype.toStateIntent = async function (state, intent) {
    console.log('do stuff here');
    return oldToStateIntent.call(this, state, intent);
};

const oldFollowUpState = Jovo.prototype.followUpState;
Jovo.prototype.followUpState = function (state) {
     console.log('do stuff here');
     return oldFollowUpState.call(this, state);
};

It would be cleaner to put it into a plugin.

class MyStateTransitionPlugin {
    install(app) {
        Jovo.prototype.toStateIntent = async function (state, intent) {
                console.log('do stuff here');
                return oldToStateIntent.call(this, state, intent);
            };

            const oldFollowUpState = Jovo.prototype.followUpState;
            Jovo.prototype.followUpState = function (state) {
                 console.log('do stuff here');
                 return oldFollowUpState.call(this, state);
            };
    }
}
app.use(new MyStateTransitionPlugin());

#5

Does ist solve your problem? Let me know if you have more questions


#6

Still deciding if we are going with this option or not. Thanks.