ECMAscript export in Node.js - javascript

Im creating an NFL football simulator in nodejs and am having trouble exporting one of my variables. As you can see in my get_teams.js i make many HTTP requests. I then process the responseArr and format the data. Where I am running into an issue is when I try and export the sorted_teams_array. you can find this code at the very bottom of get_teams.js.
I then try and import this array into tester.js and console log it. I will eventually use this file to inject a mongo database with the array, but for now am just trying to console log it and cannot get it to work. I am using the --experimental-modules in my npm scripts when I run npm run tester, and still nothing. Any help would be great! I am a noobie so please no hate!
get_teams.js
import axios from 'axios';
import Nfl_team from '../models/teamModel.js';
import Offensive_stats from '../models/offensiveStatsModel.js';
import Defensive_stats from '../models/defensiveStatsModel.js';
import Game_stats from '../models/gameStatsModel.js';
import colors from 'colors';
import dotenv from 'dotenv';
dotenv.config();
const teams = {};
function get_teams() {
axios.all([
axios.get(`https://api.sportsdata.io/api/nfl/fantasy/json/Standings/${process.env.SEASON}?key=${process.env.API_KEY}`),
// ... many more gets
])
.then(function (responseArr) {
responseArr[0].data.forEach(element => {
teams[element.Team] = new Nfl_team(element.Team, element.Name, element.Wins, element.Losses, element.Ties,
element.Percentage, element.DivisionWins, element.DivisionLosses, element.DivisionTies,
element.PointsFor, element.PointsAgainst)
});
// many more forEach blocks on responseArr[1, 2, 3...]
/* power rating algorithm logic
_____________________________________________ */
const teams_array = Object.entries(teams);
export const sorted_teams_array = teams_array.sort((a, b) => {
if (a[1].average_victory_margin > b[1].average_victory_margin) return -1;
if (a[1].average_victory_margin < b[1].average_victory_margin) return 1;
return 0;
})
console.log(sorted_teams_array);
teams_array.forEach(element => {
console.log(`average victory margin for ${element[0]} = ${element[1].average_victory_margin}`)
});
})
.catch(function (error) {
// handle error
console.log(error);
})
}
get_teams();
tester.js
import { sorted_teams_array } from './get_teams';
console.log(sorted_teams_array);
/// returns
(node:58769) ExperimentalWarning: The ESM module loader is experimental.
internal/modules/esm/resolve.js:61
let url = moduleWrapResolve(specifier, parentURL);
^
Error: Cannot find module /Users/jojovera/Documents/nflSIMULATION/teams/get_teams imported from /Users/jojovera/Documents/nflSIMULATION/teams/tester.js
at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:61:13)
at Loader.resolve (internal/modules/esm/loader.js:94:40)
at Loader.getModuleJob (internal/modules/esm/loader.js:240:28)
at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:42:40)
at link (internal/modules/esm/module_job.js:41:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
package.json
{
"name": "optionsscript",
"version": "1.0.0",
"description": "",
"main": "app.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node --experimental-modules app.js",
"afc_west": "node --experimental-modules ../nflSIMULATION/teams/afc_west.js",
"get_teams": "node --experimental-modules ../nflSIMULATION/teams/get_teams.js",
"tester": "node --experimental-modules ../nflSIMULATION/teams/tester.js",
"get_offensive_stats": "node --experimental-modules ../nflSIMULATION/teams/get_offensive_stats.js",
"get_defensive_stats": "node --experimental-modules ../nflSIMULATION/teams/get_defensive_stats.js",
"get_victory_margin": "node --experimental-modules ../nflSIMULATION/teams/get_victory_margin.js",
"power_rank": "node --experimental-modules ../nflSIMULATION/teams/power_rank.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.21.0",
"cheerio": "^1.0.0-rc.5",
"colors": "^1.4.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"nodemon": "^2.0.6",
"stats-lite": "^2.2.0",
"terminal-kit": "^1.44.0",
"tofixed": "^1.0.0"
}
}

As addressed in the comments and chat, there were two issues: ESM isn't supported in Node 12, so an update to 15 fixed that. The other issue is that nothing was validly exported from get_teams: import and export are top-level keywords, and the export was taking place inside a .then. These minor changes allow the function to be imported and its result used in the tests:
export function get_teams() {
return axios.all([
/// rest of code
return sorted_teams_array;
})
.catch(function (error) {
// handle error
console.log(error);
})
}
Usage example:
import { get_teams } from './get_teams'
get_teams.then((teams) => {
teams.forEach(console.log)
})

Related

Why does Jest keep giving me error "SyntaxError: Cannot use import statement outside a module' "? I am using Babel to transpile ES6 for Jest to test

Why do I keep getting error message "SyntaxError: Cannot use import statement outside a module" when I use Babel and Jest?
I have a super simple app that contains two modules:
// moduleTwo.mjs:
let testFuncOneModTwo = () => {
return ('String generated by fn in moduleTwo.mjs')
}
export {testFuncOneModTwo }
/////////////
// moduleOne.mjs:
import {testFuncOneModTwo} from './moduleTwo.mjs'
let testFuncOneModOne = () => {
return (testFuncOneModTwo())
}
export { testFuncOneModOne }
//////////////
Here's my Jest test file:
// myTest.test.js:
import * as myImports from './moduleOne.mjs';
test('tests fn in module that calls fn in another module.', () => {
expect(myImports.testFuncOneModOne()).toEqual( 'String generated by fn in
moduleTwo.mjs' );
});
/////////////
// babel.config.json:
{
"presets": ["#babel/preset-env"]
}
// package.json:
{
"name": "JestIsVeryTesting",
"version": "1.0.0",
"description": "",
"main": "moduleOne.mjs",
"scripts": {
"test": "jest --coverage "
},
"jest": {
"transform": {
"^.+\\.js?$": "babel-jest"
}
},
"dependencies": {
"#babel/runtime": "^7.18.6"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/plugin-transform-runtime": "^7.18.6",
"#babel/preset-env": "^7.18.6",
"babel": "^6.23.0",
"babel-jest": "^28.1.2",
"jest": "^28.1.2"
}
}
// The error message (edited by me):
Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. ...
...
...
Details:
/xxx/xxx/xxx/xxx/moduleOne.mjs:91
import { testFuncOneModTwo } from './moduleTwo.mjs';
^^^^^^
SyntaxError: Cannot use import statement outside a module
1 |
> 2 | import * as myImports from './moduleOne.mjs';
| ^
3 |
4 | test('tests fn in module that calls fn in another module.', () => {
5 | expect(myImports.testFuncOneModOne()).toEqual( 'This string returned by a function in moduleTwo.mjs' );
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1796:14)
at Object.<anonymous> (myTest.test.js:2:1)
Help would be much appreciated as this is driving me mad.
In case anyone is interested I solved the problem myself in the end:
To the top level of the package.json file I added:
"type": "module"
This tells node that all files in the project that end with '.js' are ES6 files
I changed the extensions of my modules to '.js'
(so that
'moduleOne.mjs' became 'moduleOne.js'
and
'moduleTwo.mjs' became 'moduleTwo.js'
)
This is in keeping with the value of the package.json file's "jest" field, which has value:
"transform": {
"^.+\\.js?$": "babel-jest"
}

Electron-Prisma Error: can not find module '.prisma/client'

I'm building a Nuxt-electron-prisma app and I kinda stuck here. when I use prisma normally as guided every thing is fine on dev but on build i get this error :
A javascript error occurred in the main process
Uncaught exception:
Error: can not find module : '.prisma/client'
I tried changing prisma provider output to ../resources/prisma/client
generator client {
provider = "prisma-client-js"
output = "../resources/prisma/client"
}
and in main.js of electron
const { PrismaClient } = require('../resources/prisma/client');
const prisma = new PrismaClient()
but I get error Cannot find module '_http_common' at webpackMissingModules in both dev and build ! which by others opinion is caused when using prisma on client-side but I only use it on background.js (main.js of the my boilerplate)
I'm using Nuxtron boilerplate for Nuxt-electron which is using yml file for electron-builder config file and in it I also added prisma to files property:
appId: com.example.app
productName: nuxt-electron-prisma
copyright: Copyright © 2021
nsis:
oneClick: false
perMachine: true
allowToChangeInstallationDirectory: true
directories:
output: dist
buildResources: resources
files:
- "resources/prisma/database.db"
- "node_modules/.prisma/**"
- "node_modules/#prisma/client/**"
- from: .
filter:
- package.json
- app
publish: null
and still get errors
in my win-unpacked/resources I have this only: win-unpacked\resources\app.asar.unpacked\node_modules\#prisma\engines
and of course my package.json
{
"private": true,
"name": "nuxt-electron-prisma",
"productName": "nuxt-electron-prisma",
"description": "",
"version": "1.0.0",
"author": "",
"main": "app/background.js",
"scripts": {
"dev": "nuxtron",
"build": "nuxtron build"
},
"dependencies": {
"electron-serve": "^1.0.0",
"electron-store": "^6.0.1",
"#prisma/client": "^3.0.2"
},
"devDependencies": {
"#mdi/font": "^6.1.95",
"#nuxtjs/axios": "^5.13.6",
"#nuxtjs/device": "^2.1.0",
"#nuxtjs/dotenv": "^1.4.1",
"#nuxtjs/vuetify": "1.12.1",
"core-js": "^3.15.1",
"electron": "^10.1.5",
"electron-builder": "^22.9.1",
"glob": "^7.1.7",
"noty": "^3.2.0-beta",
"nuxt": "^2.15.7",
"nuxtron": "^0.3.1",
"sass": "1.32.13",
"swiper": "^5.4.5",
"prisma": "^3.0.2",
"vue-awesome-swiper": "^4.1.1"
}
}
The solution provided by Mojtaba Barari works but it results in #prisma packages being present in both resources/app/node_modules and resources/node_modules.
There is a better way how to do it:
{
"build": {
"extraResources": [
{
"from": "node_modules/.prisma/client/",
"to": "app/node_modules/.prisma/client/"
}
],
}
}
In this case, the Prisma client files will be copied directly to resources/app/node_modules where other #prisma packages are already present and so you will save ~ 10 MB compared to the other solution.
EDIT:
My previous solution doesn't work if an application is packaged into an asar archive. You need to use files field instead:
{
"build": {
"files": [
{
"from": "node_modules/.prisma/client/",
"to": "node_modules/.prisma/client/"
}
],
}
}
This is a universal solution which works even if you don't use an asar archive.
Ok, I finally solved it!!
first of all no need to change client generator output direction!
//schema.prisma
datasource db {
provider = "sqlite"
url = "file:../resources/database.db"
}
generator client {
provider = "prisma-client-js"
// output = "../resources/prisma/client" !! no need for this!
}
then in electron-builder config add ./prisma , #prisma and database
// my config file was a .yml
extraResources:
- "resources/database.db"
- "node_modules/.prisma/**/*"
- "node_modules/#prisma/client/**/*"
// or in js
extraResources:[
"resources/database.db"
"node_modules/.prisma/**/*"
"node_modules/#prisma/client/**/*"
]
this solved `Error: cannot find module : '.prisma/client'
but this alone won't read DB in built exe file!
so in main.js where importing #prisma/client should change DB reading directory:
import { join } from 'path';
const isProd = process.env.NODE_ENV === 'production';
import { PrismaClient } from '#prisma/client';
const prisma = new PrismaClient({
datasources: {
db: {
url: `file:${isProd ? join(process.resourcesPath, 'resources/database.db') : join(__dirname, '../resources/database.db')}`,
},
},
})
with these configs I could fetch data from my sqlite DB

Importing git npm modules results in undefined

I have made a npm module in a private git repo and I'm trying to access it in another application.
I'm using reactjs, webpack and npm
So I have the module:
dist
src
| form-mapper
| formMapper.js
| myfile.js
| index.js
package.json
webpack.config.js
Webpack.config.js is like this:
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js'
}
}
Package.json is like this:
{
"name": "my-awesome-module",
"version": "1.0.0",
"license": "ISC",
"main": "./dist/bundle.js",
"scripts": {
"prepare": "npm run build",
"build": "webpack --mode production",
"start": "webpack-dev-server --open --mode development"
},
"devDependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^4.3.0",
"webpack-dev-server": "^3.11.0"
}
}
formMapper.js as 2 functions that I'm trying to export:
export function mapForm() {
// some code
}
export function mapUiFormToBackEnd() {
// some code
}
And index.js:
import * as FormMapper from './form-mapper/formMapper'
export { mapForm, mapUiFormToBackEnd } from './form-mapper/formMapper'
export default FormMapper
I've tried a lot of things in index.js so I let everything here just to show you guys what I've already tried.
In my app that needs to use this module I import the module using npm (git+ssh://...) which is working since I can see my module inside node_modules.
When I try to import using:
import FormMapper from 'my-awesome-module'
componentDidMount() {
FormMapper.mapForm()
}
I have this error:
my-awesome-module__WEBPACK_IMPORTED_MODULE_2___default.a.mapForm is not a function
That's my first time trying to create my own npm module and I clearly don't understand everything. I tried several guide but it seems I'm not abla to make it right.
Thanks for the help.
Edit:
When I log my import in my application
import FormMapper from 'my-awesome-module'
componentDidMount() {
console.log(FormMapper)
FormMapper.mapForm()
}
I see an empty object {} getting logged
update your formMapper.js in a more proper way
const mapForm = () => {
// Code here
}
const mapUiFormToBackEnd = () => {
// Code here
}
module.exports = {mapForm, mapUiFormToBackEnd }
on your index.js
// If you just want the mapForm and mapUiFormToBackEnd
const {mapForm, mapUiFormToBackEnd} = require('./form-mapper/formMapper');
// Or if you just want to get all it's fucntion just import it like this
const FormMapper = require('./form-mapper/formMapper') // No need for *
// export the whole FormMapper
module.exports = FormMapper;
// If you want to export a specific functions inside FormMapper
module.exports = {mapForm, mapUiFormToBackEnd }

Babel transpiled ES6 code (node.js) successfully, but when do "npm start" it throws "SyntaxError: Unexpected token import "

I have written a code in node.js(ES6) and below is my problem with steps i followed to run my code:
-Step1:
ES6 code==>(babel)==>successfully transpiled code when run (npm run build)
-Step2:
run command (npm start) throws error "SyntaxError: Unexpected token import"
But if i run "nodemon ./src/index.js --exec babel-node" it runs successfully.
I have also tried to understand the reason for failure by searching similar questions on stackoverflow before posting this question here but not able to make my code work.
I really appreciate your help guys i do not know how to proceed from here, our whole production deployment is stuck due to this issue:(.
Below you will find my code files which shows i have already used babel and .babelrc in my code:
Package.json-
"dependencies": {
"babel-preset-es2015": "^6.24.1",
"body-parser": "^1.16.0",
"connect-timeout": "^1.8.0",
"core-js": "^2.4.1",
"cors": "^2.8.1",
"express": "^4.14.1",
"joi": "^10.2.2",
"jsonapi-serializer": "^3.5.3",
"mongoose": "^4.10.4",
"mongoose-rename-id": "^1.0.2",
"nedb": "^1.8.0",
"path": "^0.12.7",
"randomstring": "^1.1.5",
"request": "^2.79.0",
"request-promise": "^4.1.1",
"swagger-express-mw": "^0.1.0",
"swagger-ui": "^2.2.10",
"yamljs": "^0.2.8"
},
"devDependencies": {
"babel-cli": "^6.22.2",
"babel-core": "^6.22.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-es2015-node": "^6.1.1",
"babel-preset-es2016-node4": "^6.0.1",
"babel-preset-es2017": "^6.22.0",
"chai": "^3.5.0",
"chai-as-promised": "^6.0.0",
"husky": "^0.13.1",
"mocha": "^3.2.0",
"mocha-duplicate-reporter": "^0.2.1",
"mocha-multi": "^0.9.0",
"mocha-sonar-generic-test-coverage": "0.0.1",
"nock": "^9.0.2",
"node-mocks-http": "^1.6.1",
"nodemon": "^1.11.0",
"nyc": "^10.1.2",
"pact": "^1.0.0",
"rimraf": "^2.5.4",
"sinon": "^1.17.7",
"sinon-chai": "^2.8.0",
"snazzy": "^6.0.0",
"standard": "^8.6.0",
"unit.js": "^2.0.0"
},
.babelrc-
{
"presets": [
"es2016-node4",
"es2017",
"es2015"
]
}
code for index.js:
'use strict'
import * as path from 'path'
import {PORT} from 'config'
// config module loads the configuration from the folder the process is run
process.env[ 'NODE_CONFIG_DIR' ] = path.resolve(__dirname, '/config')
import server from './server'
// Start the server
server(PORT)
code for server.js:
import cors from 'cors'
import SwaggerExpress from 'swagger-express-mw'
import bodyParser from 'body-parser'
import timeout from 'connect-timeout'
import * as YAML from 'yamljs'
import * as path from 'path'
import account from '../src/api/controllers/accounts.js'
const version = {
file: YAML.load(path.join(__dirname, 'version.yml'))
}
var config = {
appRoot: __dirname,
swaggerFile: path.resolve(__dirname, 'api', 'swagger', 'swagger.json'),
basePath: '/api/v1',
swaggerSecurityHandlers:{
basicAuth :async function(req, authOrSecDef, scopesOrApiKey, callback){
try{
//let data = true
console.log(req.headers.authorization)
let data = await account.authenticate(req.headers.authorization)
if(data.statusCode==200){
console.log(data)
callback(null,true);
}
else
callback(new Error("Access denied"))
}catch(err){
callback(new Error("Access denied"))
}
console.log("response ...."+data)
}
}
}
export default function start (serverPort) {
SwaggerExpress.create(config, function (err, swaggerExpress) {
if (err) {
throw err
}
var app = require('express')()
// Hack to override the host and port
app.get(path.resolve(config.basePath, '/api-docs'), function (req, res) {
swaggerExpress.runner.swagger.host = req.get('host')
// Set correct version for the API
swaggerExpress.runner.swagger.info.version = version.file.build.name
res.json(swaggerExpress.runner.swagger)
})
// Customize SwaggerUI
var swaggerUIParams = {
swaggerUi: config.basePath + '/docs',
apiDocs: config.basePath + '/api-docs'
}
// Add for version
app.get('/version', function (req, res) {
// Load yaml file using YAML.load
res.json(version.file.build)
})
// serves the Swagger documents and Swagger UI
app.use(swaggerExpress.runner.swaggerTools.swaggerUi(swaggerUIParams))
app.use(cors())
app.use(bodyParser.json())
app.use(timeout('6s'))
// install middleware
swaggerExpress.register(app)
app.listen(serverPort)
})
}
code for Accounts.js(here it actually throws the error at import statement first line):
import request from 'request-promise'
export default account()
function account() {
return {
authenticate: async function authenticate (authheader) {
console.log("Sending call for Account")
let temp = (authheader).split(" ")
console.log(temp[1])
let buf = new Buffer(temp[1], 'base64'); // create a buffer and tell it the
data coming in is base64
let plain_auth = buf.toString(); // read it back out as a string
console.log("Decoded Authorization ", plain_auth);
const cred = plain_auth.split(':')
const options={
uri: `http://localhost:3000/api/account/${cred[0]}`,
json: true,
resolveWithFullResponse: true,
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Accept': 'application/json; charset=utf-8'
// 'Authorization':authheader
},
method: 'GET'
}
return request(options).then((response) => {
console.log(response.statusCode)
return {
"statusCode":response.statusCode,
"body":response.body
}
}).catch((err) => {
console.log(err);
console.log('errorstatuscode:' + err.statusCode)
});
}
}
}
scripts in package.json:
"scripts": {
"build:transpile": "babel src/ -d dist",
"build:copy-resources": "cp -r config dist && cp -r src/api/swagger dist/api
&& cp src/version.yml dist",
"build": "rimraf dist && npm run build:transpile && npm run build:copy-
resources",
"devstart": "nodemon ./src/index.js --exec babel-node",
"start": "node dist/index.js",
}
Dear all the issue is resolved now, the error is in the path defined at server.js at the below line:
-import account from '../src/api/controllers/accounts.js'
There is no issue with the babel or transpiled code, its due to the wrong path definition which tells the code to pick file accounts.js from src folder not from the transpiled code present in dist folder as a result it failed and throws the error of unexpected token import.
Now i have corrected the relative path and its working fine with npm run start as well.
Thanks you all too for your support.
require babel-register module start of your index.js
require('babel-register');
I think it will solve your problem.
Your npm run build work when you are bundling code, that time babel transpile your code as per your configuration provided to webpack/gulp.
But when you start server then babel does not transpile it because babel does not aware about it.

Can not test something with mocha when I have angular (1.6) as a dependency

I want to test a ng-redux reducer wich have angular (1.6) as dependency.
When I run the tests (npm test) with mocha, I get :
/data/work/mocha-angularjs/node_modules/angular/angular.js:33343
})(window);
^
ReferenceError: window is not defined
I tried to add jsdom to provide a fake window. But it still fails during the import of angular with this error :
module.exports = angular;
^
ReferenceError: angular is not defined
Is there a way to make angular work properly in mocha/babel world ?
I made a small github project available here which reproduce the problem.
Here is the content of the project :
Package.json
{
"name": "mocha-angularjs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"angular": "^1.6.3"
},
"devDependencies": {
"babel-core": "^6.24.0",
"babel-preset-es2015": "^6.24.0",
"babel-preset-latest": "^6.24.0",
"chai": "^3.5.0",
"jsdom": "9.12.0",
"jsdom-global": "2.1.1",
"mocha": "^3.2.0"
},
"scripts": {
"test": "NODE_ENV=test mocha src/index.test.js --compilers js:babel-register --require jsdom-global/register"
},
"repository": {
"type": "git",
"url": "git+https://github.com/jtassin/mocha-angularjs.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/jtassin/mocha-angularjs/issues"
},
"homepage": "https://github.com/jtassin/mocha-angularjs#readme"
}
.babelrc
{
"plugins": [],
"presets": [
"latest",
]
}
The code to test
import angular from 'angular';
export default function getFive() {
return 5;
}
The test
import expect from 'chai';
import getFive from './index';
describe('desc', () => {
it('my test', () => {
expect(getFive()).to.equal(5);
});
});
In case of someone needs it one day :
I used angularcontext to solve the problem.
package.json
"devDependencies": {
"angularcontext": "0.0.23",
[...]
},
In my test file
/* eslint-env mocha */
/* eslint-disable import/no-extraneous-dependencies */
import angularcontext from 'angularcontext';
before((done) => {
const context = angularcontext.Context();
context.runFile('./node_modules/angular/angular.js', (result, error) => {
if (error) {
/* eslint-disable no-console */
console.error(error);
done(error);
} else {
global.angular = context.getAngular();
done();
}
});
});
/* eslint-disable import/prefer-default-export */
export const angular = global.angular;
The github project has been updated with it.

Categories