Sync Sequelize Databases on Serverless app - node.js

I am using sequelize with MySQL on the Serverless offline app.
I am not sure how to sync all models on serverless start?
I am tried to do this
import Sequelize from "sequelize";
import mysql2 from 'mysql2';
const sequelize = new Sequelize('database', 'root', '', {
dialect: 'mysql',
dialectModule: mysql2,
host: 'localhost',
});
const getSequelize = () => {
sequelize.sync({ force: false })
.then(() => {
console.log(`Database & tables synchronised!`)
});
return sequelize;
}
export default getSequelize();
This approach syncs models that are imported into controller, so the only way in this case to sync all models is to include all models in every controller.
This does not look like a good example.
Do you have any idea?

Use sequelize.sync only for development purposes. Use sequelize migrations for production.
There must be some way to run console command db:migrate in your environment. When you push all the migration code use that command to update your database to the last version.

Related

Error with pg-connection-string and sequelize in a React application

I am trying to use the sequelize ORM with a React application. I've installed the sequelize and pg-connection-string packages, but I am getting an error when trying to connect to the database. The error message is:
ERROR in ./node_modules/pg-connection-string/index.js 4:9-22
Module not found: Error: Can't resolve 'fs'
I've tried uninstalling and reinstalling the packages, clearing the npm cache, and using a different version of the packages, but I am still getting the same error.
I am using the following versions:
React: 16.13.1
Sequelize: 6.3.5
pg-connection-string: 2.0.0
Here is my code:
const Sequelize = require('sequelize');
const sequelize = new Sequelize('texteditor', 'root', '', {
host: 'localhost',
dialect: 'mysql'
});
const Database = sequelize.define('database', {
title: {
type: Sequelize.STRING
},
content: {
type: Sequelize.TEXT
}
});
sequelize
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
sequelize.sync();
I would greatly appreciate any help or suggestions on how to resolve this issue.
So typically you do not connect to databases in the UI layer of an application. Likely the reason it can't retrieve the fs module is that you're running in a browser, where the sequelize package expects you to be using the node runtime. This is where you would build a backend server using Node.JS, which would connect to the DB and in turn respond to the UI with the information it needs.

TypeORM: Generate migrations without dedicated ormconfig file

Of the several ways of connecting to a database offered by TypeORM (json, env, yml...) I choose to set my Connection Options programatically within my project's code using a regular TypeScript file as follows:
// src/database/createConnection.ts
import { createConnection } from 'typeorm';
const connectionOptions = {
type: 'postgres',
host: POSTGRES_HOST_PROD,
port: Number(POSTGRES_PORT),
username: POSTGRES_USER,
password: POSTGRES_PASSWORD,
database: POSTGRES_DB,
entities: ['build/entities/**/typeDef.js'],
migrations: ['build/database/migrations/*.js'],
cli: {
migrationsDir: 'src/database/migrations/'
}
};
await createConnection(connectionOptions);
With the values fed by a regular .env file.
My problem is that when trying to create migration files through npx typeorm migration:generate -n initial I get an error as the command expects a specific orm configuration file to be present (ormconfig.env, ormconfig.json, etc).
As I already have my connection options set, this is not only redundant, it would also be processed instead of the configuration I have already set in the .ts file, and the only solution I see would be to rename the variables in my (non-typeorm-specific) .env file to match the specific TypeORM variable names, which I'd prefer not to do.
TL:DR Is there a way of generating TypeORM migrations without creating a dedicated orm config file?
Oh, turns out TypeORM already has a built-in option for this which does not require an extra ormconfig file, one can just add the property migrationsRun: true to the Connection Options (making sure synchronize is set to false).
For instance:
import { createConnection } from 'typeorm';
const connectionOptions = {
type: 'postgres',
host: POSTGRES_HOST_PROD,
port: Number(POSTGRES_PORT),
username: POSTGRES_USER,
password: POSTGRES_PASSWORD,
database: POSTGRES_DB,
migrationsRun: true,
entities: ['build/entities/**/typeDef.js'],
migrations: ['build/database/migrations/*.js'],
cli: {
migrationsDir: 'src/database/migrations/'
}
};
await createConnection(connectionOptions);

difference between Tedious and sequelize

i am new in Backend, i started learning node, i found the ORM sequelize and it's a good to handle with database but also find tedious . i did not understand the relation between them , can i use sequelize only in my project without tedious ? i found lot of people work with the two but i did not understqand why , i mean if we can use sequelize and interact with db why we have to use tedious at the same time ?
var Connection = require('tedious').Connection;
var config = {
server: "192.168.1.210",
options: {},
authentication: {
type: "default",
options: {
userName: "test",
password: "test",
}
}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
if(err) {
console.log('Error: ', err)
}
// If no error, then good to go...
executeStatement();
});
const Sequelize = require('sequelize')
module.exports = new Sequelize('db', 'user', 'password', {
host: '',
dialect: 'mssql',
pool: {
max: 50,
min: 2,
idle: 10000
},
});
Ofcourse you can work with only sequelize. As I can see in the documentation.
Tedious is a pure-Javascript implementation of the TDS protocol, which is used to interact with instances of Microsoft's SQL Server. It is intended to be a fairly slim implementation of the protocol, with not too much additional functionality.
But sequelize will work will all db.
Sequelize is a promise-based Node.js ORM for Postgres, MySQL, MariaDB, SQLite and Microsoft SQL Server. It features solid transaction support, relations, eager and lazy loading, read replication and more.

Can Sequelize be used to connect to a new database?

In designing a simple node.js project, I tried using Sequelize to connect to a mysql server using the following configuration parameters:
{ dbname: users
username: jimmy
password: users
params:
host: localhost
port: 3306
dialect: mysql }
though the 'users' database didn't exist yet.
I got a server error:
InternalServerError: {"name":"SequelizeConnectionError","parent":{"code":"ER_BAD_DB_ERROR","errno":1049,"sqlState":"42000","sqlMessage":"Unknown database 'users'"},"original":{"code":"ER_BAD_DB_ERROR","errno":1049,"sqlState":"42000","sqlMessage":"Unknown database 'users'"}}
But the Sequelize docs: Manual | Sequelize indicate that Sequelize can connect to a new database. Please, how can Sequelize be used to connect to a
new(non-existing) database?
You should read the documentation again carefully (because the wording is indeed confusing!).
New databases versus existing databases
If you are starting a project from scratch, and your database does not exist yet, Sequelize
can be used since the beginning in order to automate the creation of
every table in your database.
Also, if you want to use Sequelize to connect to a database that is
already filled with tables and data, that works as well! Sequelize has
got you covered in both cases.
It will connect only to an existing DB, it can help you by creating the tables if they do not exist yet but the DB has to be there in order for sequelize to connect with it.
Following this question, I wrote this PR to update the documentation to be less confusing. Hope it help!
Found a similar problem on SO, and an answer by osifo:
//create the sequelize instance omitting the database-name arg
const sequelize = new Sequelize("", "<db_user>", "<db_password>", {
dialect: "<dialect>"
});
return sequelize.query("CREATE DATABASE `<database_name>`;").then(data
=> {
// code to run after successful creation.
});
So, I was able to implement it in my own code:
var SQUser;
var sequlz;
async function connectDB() {
sequlz =
new Sequelize("", "jimmy", "users", {host: "localhost", port: 3306, dialect: "mysql"});
await sequlz.query("CREATE DATABASE users;");
await sequlz.query("Use users;");
SQUser = sequlz.define('Table',
{
// define table schema
});
return SQUser.sync();
};
//use sequelize to populate the table
async function create() {
const SQUser = await connectDB();
return SQUser.create(
//values
);
}

Automated Testing with Databases

I'm fairly new to automated testing and was wondering how I should go about writing tests for the database. The project I'm working on right now is running PostgreSQL with Sequelize as the ORM on a Node.JS environment. If it matters, I'm also using Jest as the testing library right now.
In my app I use a config module to control configuration settings for different environments. When running tests the process.env.APP_ENV is set to test, and it will set the dialect to sqlite. Note that you will not have any data or data persistence, so you will need to populate it with all the data needed for your tests.
Include sqlite3
yarn add -D sqlite3
or
npm i -D sqlite3
Config
module.exports = {
database: {
name: 'dbname',
user: 'user',
password: 'password',
host: 'host',
// Use "sqlite" for "test", the connection settings above are ignored
dialect: process.env.APP_ENV === 'test' ? 'sqlite' : 'mysql',
},
};
Database/Sequelize
// get our config
const config = require('../config');
// ... code
const instance = new Sequelize(
config.database.name,
config.database.user,
config.database.password,
{
host: config.database.host,
// set the dialect, will be "sqlite" for "test"
dialect: config.database.dialect,
}
);
Test Class (Mocha)
const TestUtils = require('./lib/test-utils');
describe('Some Tests', () => {
let app = null;
// run before the tests start
before((done) => {
// Mock up our services
TestUtils.mock();
// these are instantiated after the mocking
app = require('../server');
// Populate redis data
TestUtils.populateRedis(() => {
// Populate db data
TestUtils.syncAndPopulateDatabase('test-data', () => {
done();
});
});
});
// run code after tests have completed
after(() => {
TestUtils.unMock();
});
describe('/my/route', () => {
it('should do something', (done) => {
return done();
});
});
});
Run Tests
APP_ENV=test ./node_modules/.bin/mocha
You could use ENV variables in other ways to set the dialect and connection parameters as well - the above is just an example based on what we have done with a lot of supporting code.
If you're not doing anything particularly complicated on the DB side, take a look at pg-mem:
https://swizec.com/blog/pg-mem-and-jest-for-smooth-integration-testing/
https://github.com/oguimbal/pg-mem
It's really cool in that it tests actual PG syntax and can pick up a bunch of errors that using a different DB or mock DB won't pick up. However, it's not a perfect implementation and missing a bunch of features (e.g. triggers, decent "not exists" handling, lots of functions) some of which are easy to work around with the hooks provided and some aren't.
For me, having the test DB initialized with the same schema initialization scripts as the real DB is a big win.

Resources