GraphQl , Sequelize-CLi, models bundler - sequelize.import is not a function - express

I'm following tutorial about sequelize-cli: https://andela.com/insights/using-graphql-and-sequelize/
And I'm getting an err: 'sequelize.import is not a function'
it's coming from models/index.js (which should bundle all models)
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
// Set DB Connection
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
// Import model files in models folder and make table associations where present
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
I was searching solution online but whatever I saw it didnt work.
Any ideas??

OK solved!
I havent realized that
.forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
was in the same location so the correct answer was:
.forEach(file => {
db[model.name] = file
});

Related

Shopify (Node + React) custom app: verifyRequest() issue

I'm developing a custom embedded app with Node+React.
I followed the official tutorial but if I use the verifyRequest() middleware I always get the following error when I navigate through my app's pages:
Expected a valid shop query parameter
I really can't understand what's wrong with the code.
Could anyone please help me?
Below is the server.js code
require('isomorphic-fetch');
const dotenv = require('dotenv');
const Koa = require('koa');
const next = require('next');
const { default: shopifyAuth } = require('#shopify/koa-shopify-auth');
const { verifyRequest } = require('#shopify/koa-shopify-auth');
const { default: Shopify, ApiVersion } = require('#shopify/shopify-api');
const Router = require('koa-router');
const RedisSessionStorage = require('./middleware/RedisSessionStorage')
const Cookies = require('cookies')
dotenv.config();
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SHOPIFY_API_SCOPES.split(","),
HOST_NAME: process.env.SHOPIFY_APP_URL.replace(/https:\/\//, ""),
API_VERSION: ApiVersion.April21,
IS_EMBEDDED_APP: true,
SESSION_STORAGE: new Shopify.Session.CustomSessionStorage(
RedisSessionStorage.storeCallback,
RedisSessionStorage.loadCallback,
RedisSessionStorage.deleteCallback,
),
});
const port = parseInt(process.env.PORT, 10) || 3001;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const ACTIVE_SHOPIFY_SHOPS = {[process.env.ACTIVE_SHOPIFY_SHOP]: process.env.SHOPIFY_API_SCOPES}
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
server.keys = [Shopify.Context.API_SECRET_KEY];
server.use(
shopifyAuth({
accessMode: 'offline',
afterAuth(ctx) {
const { shop, scope, accessToken } = ctx.state.shopify;
global.accessToken = accessToken
ACTIVE_SHOPIFY_SHOPS[shop] = scope;
ctx.redirect(`/?shop=${shop}`);
},
}),
);
const handleRequest = async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
};
router.get("/", async (ctx) => {
const shop = ctx.query.shop;
if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
ctx.redirect(`/auth?shop=${shop}`);
} else {
await handleRequest(ctx);
}
});
router.get("(/_next/static/.*)", handleRequest);
router.get("/_next/webpack-hmr", handleRequest);
router.get("(.*)", verifyRequest({accessMode: 'offline'}), handleRequest);
server.use(router.allowedMethods());
server.use(router.routes());
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
Have you tried with the default SESSION_STORAGE?
It looks like it's directing to /auth

Jest integration test Express REST API with Mongoose

everybody. I'm new to unit/integration testing and I'm having trouble with testing one of my API routes which involves file system operations and Mongoose model method calls. I need to be able mock mongoose model method as well as router's post method. Let me share you my router's post method.
documents.js
const { User } = require('../models/user');
const { Document } = require('../models/document');
const isValidObjectId = require('./../helpers/isValidObjectId');
const createError = require('./../helpers/createError');
const path = require('path');
const fs = require('fs');
const auth = require('./../middlewares/auth');
const uploadFile = require('./../middlewares/uploadFile');
const express = require('express');
const router = express.Router();
.
.
.
router.post('/mine', [auth, uploadFile], async (req, res) => {
const user = await User.findById(req.user._id);
user.leftDiskSpace(function(err, leftSpace) {
if(err) {
return res.status(400).send(createError(err.message, 400));
} else {
if(leftSpace < 0) {
fs.access(req.file.path, (err) => {
if(err) {
res.status(403).send(createError('Your plan\'s disk space is exceeded.', 403));
} else {
fs.unlink(req.file.path, (err) => {
if(err) res.status(500).send('Silinmek istenen doküman diskten silinemedi.');
else res.status(403).send(createError('Your plan\'s disk space is exceeded.', 403));
});
}
});
} else {
let document = new Document({
filename: req.file.filename,
path: `/uploads/${req.user.username}/${req.file.filename}`,
size: req.file.size
});
document.save()
.then((savedDocument) => {
user.documents.push(savedDocument._id);
user.save()
.then(() => res.send(savedDocument));
});
}
}
});
});
.
.
.
module.exports = router;
documents.test.js
const request = require('supertest');
const { Document } = require('../../../models/document');
const { User } = require('../../../models/user');
const mongoose = require('mongoose');
const fs = require('fs');
const path = require('path');
const config = require('config');
let server;
describe('/api/documents', () => {
beforeEach(() => { server = require('../../../bin/www'); });
afterEach(async () => {
let pathToTestFolder = path.join(process.cwd(), config.get('diskStorage.destination'), 'user');
await fs.promises.access(pathToTestFolder)
.then(() => fs.promises.rm(pathToTestFolder, { recursive: true }))
.catch((err) => { return; });
await User.deleteMany({});
await Document.deleteMany({});
server.close();
});
.
.
.
describe('POST /mine', () => {
let user;
let token;
let file;
const exec = async () => {
return await request(server)
.post('/api/documents/mine')
.set('x-auth-token', token)
.attach('document', file);
}
beforeEach(async () => {
user = new User({
username: 'user',
password: '1234'
});
user = await user.save();
user.leftDiskSpace(function(err, size) { console.log(size); });
token = user.generateAuthToken();
file = path.join(process.cwd(), 'tests', 'integration', 'files', 'test.json');
});
.
.
.
it('should return 400 if an error occurs during calculation of authorized user\'s left disk space', async () => {
jest.mock('../../../routes/documents');
let documentsRouter = require('../../../routes/documents');
let mockReq = {};
let mockRes = {}
let mockPostRouter = jest.fn();
mockPostRouter.mockImplementation((path, callback) => {
if('path' === '/mine') callback(mockReq, mockRes);
});
documentsRouter.post = mockPostRouter;
let error = new Error('Something went wrong...');
const res = await exec();
console.log(res.body);
expect(res.status).toBe(400);
expect(res.body.error).toHaveProperty('message', 'Something went wrong...');
});
.
.
.
});
});
What I want to do is, I need to be able call a mock user.leftDiskSpace(function(err, leftSpace)) user model method inside router.post('/mine', ...) route handler. I need to be able to get inside the if and else brances by callback function of user.leftDiskSpace(). How can I do that?
Thanks in advance.

sequelize raw query in express app

I'm trying to call a simple sequelize raw query to get all the users in the users table but I am getting the error.
Cannot read property 'query' of undefined
what am I doing wrong here?
models/index.js
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(module.filename);
const env = process.env.NODE_ENV || 'development';
const config = require(`${__dirname}/../config/config.json`)[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
sequelize = new Sequelize(
config.database, config.username, config.password, config
);
}
fs
.readdirSync(__dirname)
.filter(file =>
(file.indexOf('.') !== 0) &&
(file !== basename) &&
(file.slice(-3) === '.js'))
.forEach(file => {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
module.exports = db;
controllers/users
const db = require('../models/index').db;
module.exports = {
getAllUsers(req, res){
db.query('SELECT * FROM "Users" As Users', { type: sequelize.QueryTypes.SELECT})
.then(result => {
return res.status(201).send({
result
});
})
}
};
Had to change
const db = require('../models/index').db;
to
const db = require('../models/index');
and add const sequelize = require('sequelize');

Import sequelize model in vuejs

I'm building a CRUD app using electron + vuejs + sequelize, i have used sequelize init and configured the .sequelizerc as below
const path = require('path');
module.exports = {
'config': path.resolve('src/renderer/database/config', 'config.json'),
'models-path': path.resolve('src/renderer/database', 'models'),
'seeders-path': path.resolve('src/renderer/database', 'seeders'),
'migrations-path': path.resolve('src/renderer/database', 'migrations')
}
Now i'm trying to populate a table with data from the database, I've tried to import the models in many ways, always leading to errors.
Error: Uncaught TypeError: Path must be a string. Received undefined
Component:
var models = require('./../../database/models'); // LINE WITH ERROR
export default {
name: "user-index",
data: function() {
return {
users: []
};
},
created: function() {
models.Users.findAll().then(users => {
//
});
},
components: {},
methods: {}
};
Thanks.
EDIT:
I found the problem, it is in the models/index.js:
'use strict';
var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var basename = path.basename(__filename);
var env = process.env.NODE_ENV || 'development';
var config = require(__dirname + '/../config/config.json')[env];
var db = {};
if (config.use_env_variable) {
var sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
var sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
var model = sequelize['import'](path.join(__dirname, file)); // THIS LINE
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
I fixed by changing path.join to path.resolve and changing this:
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
to
for (var modelName in db) {
if (db[modelName].associate) {
db[modelName].associate(db);
}
}
in models/index.js file.

BodyParser Express, I've got Object inside Object

I am trying post some data on a server but doesn't work because I am getting something like { '{\n "rate" : "26"\n}': '' }.
----App.js
const express = require('express'),
mongoose = require('mongoose'),
bodyParser = require('body-parser');
const db = mongoose.connect('mongodb://localhost/invoiceAPI');
app = express(),
port = process.env.PORT || 3000,
Rate = require('./models/rateModel'),
Client = require('./models/clientModel'),
Invoice = require('./models/invoiceModel');
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
const invoiceRouter = require('./routes/invoiceRoutes')(Invoice),
clientRouter = require('./routes/clientRoutes')(Client),
rateRouter = require('./routes/rateRoutes')(Rate);
app.use('/api/invoices', invoiceRouter);
app.use('/api/clients', clientRouter);
app.use('/api/rates', rateRouter);
app.listen(port, () => {
console.log('Gulp is running on port ' + port);
});
---The rateRoutes file:
const express = require('express');
const rateRoutes = (Rate) => {
const rateRouter = express.Router();
rateRouter.route('/')
.get((req,res) => {
Rate.find((err,rates) => {
if(err){
res.status(500).send(err);
}
else res.json(rates);
});
})
.post((req,res) => {
console.log(req.body);
let rate = new Rate(req.body);
rate.save();
res.status(201).send(rate);
});
return rateRouter;
}
module.exports = rateRoutes;
When I execute the post with {"rate": 26} I got
{ '{\n "rate" : "26"\n}': '' }
I read something about the order of bodyParser, but doesn't work.