Help to upgrade forest V7

Hello, I’m trying to update to the latest version of forest, but I don’t know how to include the update of objectMapping and connections on my file /services/sequelize.

Here is my initialisation in index.js:

const { objectMapping, connections } = require(`${process.env.PWD}/api/services/sequelize`);

async function forestInitialization (app) {
    app.use(await Liana.init({
      envSecret: process.env.FOREST_ENV_SECRET,
      authSecret: process.env.FOREST_AUTH_SECRET,
      objectMapping,
      connections
    }))
}

module.exports = forestInitialization(app)

Here is my file /api/services/sequelize:

const Sequelize = require ('sequelize')
const config =    require (`${process.env.PWD}/config/sequelize`)
const db =      {}

// ---
const databasesConfiguration = require('../../config/databases');
const connections = {};
// ----

global.Model =    Sequelize.Model
global.Op =     Sequelize.Op

Sequelize.DataTypes.postgres.DECIMAL.parse = parseFloat

config.logging = config.logging && (message => {
  if (message.includes ('CREATE')) {
    console.info (message.green)
  } else if (message.includes ('DELETE')) {
    console.info (message.red)
  } else if (message.includes ('UPDATE')) {
    console.info (message.blue)
  } else if (message.includes ('INSERT')) {
    console.info (message.green)
  } else {
    console.info (message.grey)
  }
}) || false

const namespace = require ('cls-hooked').createNamespace ('transaction_namespace')
Sequelize.useCLS (namespace)
const sequelize = new Sequelize (config.database, config.username, config.password, {
  ...config,
  define: {
    underscored: true,
    paranoid: true,
    deletedAt: 'deleted_at',
    updatedAt: 'updated_at',
    createdAt: 'created_at',
    ...(config.define || { }),
    hooks: {
      beforeCreate: async function (instance, { transaction }) { },
      afterCreate: async function (instance, { transaction }) { },
      beforeUpdate: async function (instance, { transaction }) { },
      afterUpdate: async function (instance, { transaction }) { }
    }
  }
})

sequelize.beforeDefine (function (attributes) {
  attributes.remarks = {
    type: data_type.JSON
  }
})

global.data_type = Sequelize
global.Sequelize = Sequelize
global.sequelize = sequelize

fs.readdirSync (`${process.env.PWD}/api/models`).filter (file => /^[a-z_]*.js/.test (file) ).map (file => {
  db[file.replace (/\.js$/, '')] = require (`${process.env.PWD}/api/models/${file}`).init (sequelize, Sequelize)
})

for (let model_name of Object.keys (db).filter (model_name => db[model_name].associate)) {
  db[model_name].associate (db)

  Object.keys (db[model_name].prototype).map (key => {
    if (typeof db[model_name].prototype[key] === 'function') {
      db[model_name].prototype[key.decamelized] = db[model_name].prototype[key]
    }
  })
}

try {
  sequelize.sync ({
    force: config.force,
    logging: config.logging
  }).catch (error => {
    console.error (error)
  })
} catch (error) {
  console.error (error)
}

sequelize.query = function () {
  let args = arguments

  return Sequelize.prototype.query.apply (this, arguments).catch (function (error) {
    throw console.error ({
      sql: (args[0].sql && args[0].sql.query || args[0].query || '').replace (/\$[0-9]+/g, pattern_found => {
        let element = args[0].bind[pattern_found.replace ('$', '') / 1 - 1]

        return typeof element === 'string' && `'${element}'` || element
      }) || args[0].sql || args[0],
      stack: (error.stack || '').split ('\n')[0],
      hint: arguments[0].original.hint
    })
  })
}

Model.prototype.add_remark = async function ({ remark, remarks = [] } = { }, { user = '' } = { }) {
  console.function_called (`[${this[this.constructor.primaryKeyAttributes[0]]}]`)

  await this.update ({
    remarks: {
      ...[...remarks, remark].filter (Boolean).reduce ((result, remark) => {
        result[now_minimal ()] = `${user && `[${user}] ` || ''}${remark}`
        return result
      }, { }),
      ...this.remarks
    }
  })
}

Sequelize.models = db
db.sequelize = sequelize
db.Sequelize = Sequelize
global.namespace = namespace
global.models = db

//----
db.objectMapping = Sequelize;
db.connections = connections;
//----

module.exports = db

Thank you for your help.

Hi @didouche :wave: welcome to our community.
I see you have a very different model/index.js than us.
I suggest you to not modify your /api/services/sequelize and just modify the initialization

const { Sequelize, sequelize } = require(`${process.env.PWD}/api/services/sequelize`);

async function forestInitialization (app) {
    app.use(await Liana.init({
      envSecret: process.env.FOREST_ENV_SECRET,
      authSecret: process.env.FOREST_AUTH_SECRET,
      objectMapping: Sequelize,
      connections: { default: sequelize },
    }))
}

after this modification it should be work as before.
let me know if that help

Hi @Arnaud_Moncel and thanks for your answer.

I did as mentioned, once launched, I have this on forest admin:

“Your server encountered an error
Please check your server logs for more information. If the error persists, please let us know.”

and no error logs.

the only logs I have are juste warnings :

[forest] 🌳🌳🌳  DEPRECATION WARNING: Declaring `values` in a Smart Action is deprecated. Please use `load` hook.

Also @Arnaud_Moncel , we didn’t have any FOREST_ENV_SECRET and FOREST_AUTH_SECRET.
So I’ve taken some randomly, because I didn’t find them anywhere, maybe that’s the problem ?

To try to see what is happening can you share me your project name please.

I finally found the FOREST_ENV_SECRET and FOREST_AUTH_SECRET and now I can not be connected, I have this:

My project name is ZACK

I missed one thing,

Your error makes me think about a missing env variable.
Have you follow our migration note more precisely this section https://docs.forestadmin.com/documentation/how-tos/maintain/upgrade-notes-sql-mongodb/upgrade-to-v7#authentication?

Yes, I’ve added APPLICATION_URL in my .env, but still the same, I have the message “Unable to authenticate you”.

Have you got any error logs in your browser console ?

Yes, I do have a problem to authenticate

That the problem! the call to the authentication is not unreachable!
Have you got any server error logs? Have you set properly the APPLICATION_PORT variable?

Right, I didn’t have APPLICATION_PORT variable.
I’ve added it, still the same.

All I have on my logs are warnings above and this:

ExperimentalWarning: The dns.promises API is experimental

We don’t have access anymore to our forest admin in production, do you know why ?
We had access to it before we tried to implement new version

Hi @didouche ! Did you specify a dns in your app ?
Are you still getting a 404 error on the authentication route ?

Hi @Nicolas_Sailly !
No I didn’t specify a dns.

Yes, we still have the 404 on production (and in local environment as well)

On the network tab of your browser console, you should see two call to the authentication route, does the OPTION call fails too ? If yes can you share a screen of the request ?

Can you check that your production environment is up and running ? Maybe something fails when you try to start it… :thinking:

@Nicolas_Sailly I only have one call to the authentication route, as you can see here:

My production is up and running. but no access to forest admin

In the network tab you should see two calls, you share a screen from the console tab :slight_smile:
I’m looking for something like this:
Screenshot 2021-05-26 at 10.27.13

But with an OPTION request method

The only call I have is a POST method (here is my production call)