using babel-register with dynamically added exports results to undefined - javascript

I am having a file, where I create exports dynamically like:
import fs from 'fs';
import path from 'path';
import Sequelize from 'sequelize';
import config from '../config';
const sequelize = new Sequelize(config.database.name, config.database.user, config.database.password, {
dialect: 'postgres',
host: config.database.host,
logging: false,
define: {
underscored: true
}
});
const db = {
sequelize,
Sequelize
};
fs
.readdirSync(__dirname)
.filter(function(file) {
return (file.indexOf('.') !== 0) && (file !== 'index.js');
})
.forEach(function(file) {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName) {
if ('associate' in db[modelName]) {
db[modelName].associate(db);
}
});
export default db;
With babel 5 register hook this kind of code was working just fine. Now I was about to upgrade to babel 6 and so I used require('babel-register'). It is working fine, except that if I want to call the dynamic added attributes like
import { sequelize } from './the_above_file';
then the variable sequelize is always undefined.
But if I call
import db from './the_above_file';
then db.sequelize has a value.
Is there a way to fix it or do I have to avoid dynamic values in the export;

import { sequelize } from './the_above_file'; should have never worked since you don't have a named export with that name. You only have a default export which is an object. Properties of the default export are not the same as having named export.
That was considered a bug in Babel 5 and Babel 6 fixed it.
You can do
import db from './the_above_file';
const { sequelize } = db;
to extract the property sequelize of your default export.

Related

Jest doesn't recognize awilix container

Here is my code:
babel.config.cjs
module.exports = {
plugins: ['#babel/plugin-transform-modules-commonjs'],
presets: [['#babel/preset-env', { targets: { node: 'current' } }]]
}
jest.config.cjs
module.exports = {
globals: {
"ts-jest": {
isolatedModules: true,
},
},
};
Setup.ts
import awilix from 'awilix';
import express from 'express';
import CognitoSC from './Service/Cognito.js'
import authController from './Controller/Auth.js';
const app = express();
const container = awilix.createContainer({
injectionMode: awilix.InjectionMode.CLASSIC
});
auth.test.ts
import request from 'supertest';
import app from '../Setup.js';
describe('Testing Authentication/Authorization', function() {
it('responds with json', async function() {
const response = await request(app)
.post('/signin')
.send('username=Test')
.send('password=Testtest123$')
expect(response.status).toEqual(200);
expect(response.body.data.success).toEqual(true);
});
});
and I build it with tsc ("module": "es2022"). When I run npx jest I get an error saying
TypeError: Cannot read properties of undefined (reading 'createContainer')
> 8 | const container = awilix.createContainer({
Interesting thing that I noticed is that if I open Setup.js file which is generated by tsc and change the code from
import awilix from 'awilix';
to
const awilix = require('awilix');
and run npx jest, the tests pass without a problem. I'm little lost and can't figure out what is the problem. I also checked inside Setup.js and express is imported without a problem using ES6 syntax but why it can't do the same with awilix?
It doesn't appear that awilix supports modules.
From their readme they say to use const awilix = require('awilix') .
See here for more information about import/require/ES modules/commonJS.

Next.js does not recognize dynamic routes with square brackets names

I have this directory structure:
- pages
- api
- products
- pro
- [id].js
- add.js
[id].js
import { upload, baseHandler } from 'helpers';
import { sequelize } from 'lib';
import { init, Suppliers, Products} from 'models';
import { supplierController, productController } from 'controllers';
const handler = baseHandler.get( async (req, res) => {
const {
query: { id, name },
method,
} = req
init()
res.status(400).json(id)
})
export default handler;
export const config = {
api: {
bodyParser: false,
},
};
The static routes works fine but not the dynamic ones. I get this error when I try to access them
error - Error: getaddrinfo ENOTFOUND api.example.com
which means Next.js does not add dynamic routes from the file system.

express.session undefined in typescript

I am very new to typescript/javascript, I am trying to build backend rest apis with session
following is app.ts file
import express from "express";
import { applyMiddleware, applyRoutes } from "./utils";
import routes from "./services";
const app = express();
var ses= {
secret: "secret_session",
resave: true,
saveUninitialized: true,
cookie: { maxAge: 3600000,secure: false, httpOnly: true
}
if (app.get('env') === 'production') {
app.set('trust proxy', 1)
ses.cookie.secure = true
}
app.use(session(ses));
applyRoutes(routes, app);
I have started the server and applied the middlewares for error handling but those are not related to question in my opinion so I'm not adding code for it. Following is my routes.ts code where I'm trying to set the session.
import { Request, Response } from "express";
import { getAll, getByKeyword, addNewProduct } from "./productControllers";
{
path: "/api/v1/getAllProducts",
method: "get",
handler: [
(req: Request, res: Response) => {
getAll()
.then((row: any) => {
var sess = req.session;
sess.views = 1;
res.status(200).json({ data: row });
})
.catch(err => {
res.json({
message: err
});
});
}
]
}
I'm getting error at sess.views = 1;
I have tried the suggested questions before asking it, none of them were of any help to me.
EDIT:
I have created an index.ts
import searchRoutes from "./products/routes";
export default [...searchRoutes];
I have another util class
export const applyRoutes = (routes: Route[], router: Router) => {
for (const route of routes) {
const { method, path, handler } = route;
(router as any)[method](path, handler);
}
}
You are using an interface which is Request for express.js. But it doesn't have type definition for session. So typescript throws a compile error. To solve it you need to define session type under Request interface.
You could define a session.d.ts file under your project. And create required types & interfaces. Like:
declare global {
namespace Express {
interface Request {
session?: Session;
sessionID?: string;
}
}
}
interface Session{
mySessionVarible:string
}
But the good thing is we have DefinitilyTyped project which you can find many type definitions. This needs to solve your compile problem.
npm install --save-dev #types/express-session
And don't forget to change your import for Request.
import { Request, Response } from "#types/express-session";

ReferenceError when using MongoDB Collection variable in external resolver file that was imported via mergeResolvers

This is a totally reduced example to better explain the issue! So when I use the resolver Query getAllUsers, the MongoDB Collection Users is not available in the external resolver file user.js. So when I send that query I get:
ReferenceError: Users is not defined
That's a correct behaviour. But I do not want to include all the resolvers in my index.js, because I have a better modularization in this way. So I have all my typedefs and resolvers in external files like this.
Current file structure
index.js
/graphql
/typdef
user.graphql
/resolver
user.js
The user.graphql schema is correctly working. It is just the user.js that is producing the error when I execute the query with the not available Users variable, as already said.
Here the index.js and user.js.
index.js
import express from 'express'
import cors from 'cors'
const app = express()
app.use(cors())
import bodyParser from 'body-parser'
import {graphqlExpress, graphiqlExpress} from 'graphql-server-express'
import {makeExecutableSchema} from 'graphql-tools'
import {fileLoader, mergeTypes, mergeResolvers} from 'merge-graphql-schemas';
import {writeFileSync} from 'fs'
const typeDefs = mergeTypes(fileLoader(`${__dirname}/graphql/typedef/*.graphql`), { all: true })
writeFileSync(`${__dirname}/graphql/typedef.graphql`, typeDefs)
export const start = async () => {
try {
const MONGO_URL = 'mongodb://localhost:27017'
const MongoClient = require('mongodb').MongoClient;
MongoClient.connect(MONGO_URL, function(err, client) {
console.log("Connected successfully to server");
const db = client.db('project');
const Users = db.collection('user')
});
const URL = 'http://localhost'
const homePath = '/graphql'
const PORT = 3001
app.use(
homePath,
bodyParser.json(),
graphqlExpress({schema})
)
app.use(homePath,
graphiqlExpress({
endpointURL: homePath
})
)
app.listen(PORT, () => {
console.log(`Visit ${URL}:${PORT}${homePath}`)
})
} catch (e) {
console.log(e)
}
}
user.js
export default {
Query: {
getAllUsers: async () => {
return (await Users.find({}).toArray()).map(prepare)
}
}
}
What is the best way to pass the MongoDB or the Users collection to the resolver files. Or is there an even better solution for this issue?
First of all, this is NOT a proper solution, because declaring global variables while outsourcing schema is a bad design at all. But it works out and maybe this way someone gets an idea about how to improve this fix.
So to solve the issue all I had to do is changing the variable from local const to global.
So in index.js const Users = db.collection('user') is rewritten by global.Users = db.collection('user').
Same for the user.js. Here return (await Users.find({}).toArray()).map(prepare) is rewritten by return (await global.Users.find({}).toArray()).map(prepare).

Apollo Server - GraphQL Error: There can be only one type named "Query"

I am new to GraphQL. I am following several guides on Internet in order to "create" a small app that uses Apollo Server + Express + GraphQL + MongoDB.
I have tried to replicate this YT guide (he creates root.js file on typeDefs folder).
This one for testing purposes.
And this one to make sure my folder structure is correct.
I am getting from GraphQL when compiling:
Error: There can be only one type named "User".
Error: There can be only one type named "Query".
I have structured my code like this:
config
models
resolvers
index.js
user.js
typeDefs
index.js
root.js
user.js
index.js
Until now, my code looks like this:
typeDefs/user.js:
import { gql } from 'apollo-server-express';
const user = gql`
type User {
id: ID!
name: String
email: String
password: String
}
type Query {
getUsers: [User]
}
type Mutation {
addUser(name: String!, email: String!, password: String!): User
}
`;
export default user;
typeDefs/root.js:
import { gql } from 'apollo-server-express';
export default gql`
extend type Query {
_: String
}
type User {
_: String
}
`;
typeDefs/index.js:
import root from './root';
import user from './user';
export default [
root,
user
];
And then in my index.js:
import express from 'express';
import { ApolloServer, gql } from 'apollo-server-express';
import typeDefs from './typeDefs';
import resolvers from './resolvers';
const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.applyMiddleware({ app });
app.disable('x-powered-by');
app.listen({ port: 4000 }, () => {
console.log(`Server running at http://localhost:4000${server.graphqlPath}`)
});
What am I doing wrong?
When following the pattern of deep modularization, where you want to have each type definition in its own file, and each set of resolvers in their own file, you want to use the extend keyword and create "empty" definitions.
Supposing that you have root and user type definitions in separate files, your index file that puts them together should look like this:
const user = require('./user');
const root= require('./root');
const typeDefs = gql`
type Query{
_empty: String
}
type Mutation {
_empty: String
}
${user}
${root}
`;
module.exports = typeDefs;
You're using
type Query{
_empty: String
}
to make an empty Query. Then you're adding your user and root at the end.
Within your user file, you'd want this:
extend type Query {
getUsers: [User]
}
So the extend keyword is you extending the empty query you created in your index file.
You can read more on modularization here https://blog.apollographql.com/modularizing-your-graphql-schema-code-d7f71d5ed5f2

Categories

Resources