Implement data storage
Implement a Storage interface to enable the Miro class to automatically manage access and refresh tokens.
Goal
This guide features two examples that demonstrate how to implement a custom Storage interface to add data storage functionality to the Miro class. 
The default is a simple in-memory implementation.
For production deployments, we recommend using a custom implementation backed by a database.
Implement storage with a Redis backend
This example implements storage using:
- The Redis database as a backend.
 - The Node-Redis library library to connect to a Redis instance.
 
Create a class to handle:
- Connecting to a Redis instance.
 - Fetching state from Redis.
 - Saving state in Redis.
 - Deleting state from Redis.
 
In the example, the class name is RedisStorage:
const redis = require('redis')
class RedisStorage {
  // Initiate a connection to the Redis instance.
  // On subsequent calls, it returns the same Redis connection
  async _getClient() {
    if (!this.redisClient) {
      const client = redis.createClient()
      await client.connect()
      this.redisClient = client
    }
    return this.redisClient
  }
  // Return the state from Redis, if this data exists
  async get(userId) {
    const client = await this._getClient()
    const value = await client.get(userId.toString())
    if (!value) return undefined
    return JSON.parse(value)
  }
  // Store the state in Redis.
  // If the state is undefined, the corresponding Redis key is deleted
  async set(userId, state) {
    const client = await this._getClient()
    // Delete the state, if it's undefined
    if (!state) return await client.del(userId.toString())
    // Store the state in Redis
    await client.set(userId.toString(), JSON.stringify(state))
  }
}
To use the class, pass it as a parameter in the Miro constructor:
const miro = new Miro({
  storage: new RedisStorage(),
})
Implement storage with express-session
express-sessionThis example implements storage using:
- The Express web framework.
 - The express-session middleware to enable storing 
Mirostate information in the session storage. 
The following code example:
- Creates a new 
Miroinstance for each request. - Loads the state of the current 
Miroinstance from the session storage. - Saves the state of the current 
Miroinstance to the session storage. 
// Set up session middleware before: 'app.use(session({...}))'
app.use((req, res, next) => {
  // Create a separate 'Miro' instance for each request
  req.miro = new Miro({
    // Define the storage implementation inline
    storage: {
      // Load the 'Miro' state from the session object, if it exists
      get(_userId) {
        return req.session.state
      },
      // Store the 'Miro' state in the session object
      set(_userId, state) {
        req.session.state = state
      },
    },
  })
  next()
})
Instead of using a global miro variable, each request has a separate Miro instance associated with req.miro. 
The client endpoints that interact with the Miro API use req.miro to handle session data.
Example:
app.get('/', async (req, res) => {
  if (!await req.miro.isAuthorized(req.session.id)) {
    res.redirect(req.miro.getAuthUrl())
    return
  }
  // ...
}
See also
Updated 9 months ago
Build a more complex app that implements OAuth authentication and uses the Express web framework.