Feature(s) impacted
forest schema:update
Observed behavior
Running the command, I get an error Cannot read properties of null (reading 'replace')
Expected behavior
It updates the schema
Context
Just trying to do a simple update to add a few new columns from a single table.
Possibly related: I’m also seeing an error when trying to run a local instance.
An error occurred while computing the Forest schema. Your application schema cannot be synchronized with Forest. Your admin panel might not reflect your application models definition. Cannot read properties of undefined (reading 'options')
- Project name: scratch-payment-service
- Environment name: All
- Agent technology: nodejs
- Agent (forest package) name & version:
"forest-express-sequelize": "9.3.9"
, forest-cli/4.3.1
- Database type: mysql & 2x psql
- Recent changes made on your end if any: no
Hello @Brett_Belka and welcome back to the community.
Would you be able to provide the full stack of the error that you are getting ?
Thanks
Someone from our Customer Success team will get in touch with you directly about this issue.
[forest] 🌳🌳🌳 An error occurred while computing the Forest schema. Your application schema cannot be synchronized with Forest. Your admin panel might not reflect your application models definition. Cannot read properties of undefined (reading 'options')
{
"stack": "TypeError: Cannot read properties of undefined (reading 'options')\n at Object.getDatabaseType (/Users/brettbelka/code/scratch-admin/node_modules/forest-express-sequelize/dist/index.js:83:46)\n at _callee3$ (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/dist/index.js:164:57)\n at tryCatch (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/regeneratorRuntime.js:86:17)\n at Generator._invoke (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/regeneratorRuntime.js:66:24)\n at Generator.next (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/regeneratorRuntime.js:117:21)\n at asyncGeneratorStep (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)\n at _next (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9)\n at /Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/asyncToGenerator.js:32:7\n at new Promise (<anonymous>)\n at /Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/asyncToGenerator.js:21:12\n at _generateAndSendSchema (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/dist/index.js:234:33)\n at generateAndSendSchema (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/dist/index.js:122:33)\n at _callee$ (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/dist/index.js:368:42)\n at tryCatch (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/regeneratorRuntime.js:86:17)\n at Generator._invoke (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/regeneratorRuntime.js:66:24)\n at Generator.next (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/regeneratorRuntime.js:117:21)\n at asyncGeneratorStep (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)\n at _next (/Users/brettbelka/code/scratch-admin/node_modules/forest-express/node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9)"
}
models/index.js
const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const databasesConfiguration = require('../config/databases');
const db = {};
const connections = {};
databasesConfiguration.forEach((databaseInfo) => {
if (databaseInfo.connection.url === 'false') return
const connection = new Sequelize(databaseInfo.connection.url, databaseInfo.connection.options);
connections[databaseInfo.name] = connection;
db[databaseInfo.name] = {}
const modelsDir = databaseInfo.modelsDir || path.join(__dirname, "models", databaseInfo.name);
fs
.readdirSync(modelsDir)
.filter((file) => file.indexOf('.') !== 0 && file !== 'index.js')
.forEach((file) => {
try {
const model = require(path.join(modelsDir, file))(connection,Sequelize.DataTypes);
db[databaseInfo.name][model.name] = model;
} catch (error) {
console.error('Model creation error: ' + error);
}
});
});
Object.keys(db).forEach((database) => {
Object.keys(db[database]).forEach((modelName) => {
if ('associate' in db[database][modelName]) {
db[database][modelName].associate(db[database]);
}
})
});
db.Sequelize = Sequelize;
db.connections = connections;
module.exports = db;
middlewares/forestadmin/index.js
const path = require("path");
const Liana = require("forest-express-sequelize");
const { Sequelize, connections } = require("../../models");
// eslint-disable-next-line func-names
module.exports = async function(app) {
app.use(
await Liana.init({
configDir: path.join(__dirname, "../../forest"),
envSecret: process.env.FOREST_ENV_SECRET,
authSecret: process.env.FOREST_AUTH_SECRET,
connections,
objectMapping: Sequelize
})
);
// eslint-disable-next-line no-console
console.log(
"Your admin panel is available here: https://app.forestadmin.com/projects"
);
};
config/databases
module.exports = [
{
name: "payment",
modelsDir: path.resolve(__dirname, "../models/payment"),
connection: {
url: paymentDatabase.url,
options: { ...paymentDatabase.options }
}
},
{
name: "scratch",
modelsDir: path.resolve(__dirname, "../models/scratch"),
connection: {
url: scratchDatasource.url,
options: { ...scratchDatasource.options }
}
},
{
name: "practice",
modelsDir: path.resolve(__dirname, "../models/practice"),
connection: {
url: practiceDatasource.url,
options: { ...practiceDatasource.options }
}
}
];
Hey @Brett_Belka
Would it be possible for you to console.log(db.connections);
in both models/index.js
& console.log(connections)
in middlewares/forestadmin/index.js
, and share the output with me here (Don’t forget to remove secrets if any are displayed in the output )
According to the stacktrace shared during the call, it seems like Object.values(opts.connections)[0]
is null
in your case, and I want to make sure that’s not the case.
Thanks in advance
1 Like
@jeffladiray THANKS! I had tried that before but this time I saw the issue (there were no connections). Line 10 of models/index.js
is, indeed new. if (databaseInfo.connection.url === 'false') return
and this caused some issues with the way I had my config set in my local .env.
There’s also a strange behavior where our IAM auto-auth seems to be working when running this project locally but not for the other two, so I need to pass user and pw for two connections but only user for the third. But this is likely unrelated to FA…
1 Like
Thanks for the update.
Let me know if I can help in any way