Node.js use mssql for accessing database - javascript

I'm making the Meteor.js app and I have to get data from mssql database. I use Meteor 1.8 and a npm package - mssql(version 5.1.0). That's my code:
const sql = require('mssql')
const config = {something}
export default function fetch(query) {
const config = {something}
sql.connect(config, err => {
if (err) {
console.error(err)
return
}
// create Request object
var request = new sql.Request()
// query to the database and get the records
request.query(query, (err, recordset) => {
if (err) {
console.error(err)
return
}
return recordset
})
})
}
And I have such error
TypeError: sql.connect is not a function
I don't know what's going on, I tried to do it in many ways and I failed. When I use ConnectionPool I see an error saying that ConnectionPool is not a constructor.
What is the proper way to do this?
In my config file I have: user, password, server, database, port.

It appears to be because you're mixing your module systems, you're using require (which is CommonJS-like) but in something that's apparently an ECMAScript module (ESM) (from the export default ...). Node.js itself won't let you do that, but if you're using some kind of bundler or transpiler, perhaps it might...
Changing your require to:
import sql from "mssql";
...and making sure Node.js is using ESM¹, I don't get any error with sql.connect not being a function.
¹ In my case, since I'm using Node.js v12, I do that by having "type": "module" in my package.json and running it via node --experimental-modules filename.js, more here.

Related

Firebase module requires an older version of node while deploying the functions

I want to make a cloud function that uses 'firebase' module (not a 'firebase-functions')
And when I'm using or even only import it, npm throws an error:
Error: Error parsing triggers: Failed to load gRPC binary module because it was not installed for the current system
Expected directory: node-v64-darwin-x64-unknown
Found: [node-v79-darwin-x64-unknown]
This problem can often be fixed by running "npm rebuild" on the current system
Original error: Cannot find module '/Users/rame/functions/node_modules/grpc/src/node/extension_binary/node-v64-darwin-x64-unknown/grpc_node.node'
1) If you want to compile the package/file into executable, please pay attention to compilation warnings and specify a literal in 'require' call. 2) If you don't want to compile the package/file into executable and want to 'require' it from filesystem (likely plugin), specify an absolute path in 'require' call using process.cwd() or process.execPath
here's my code on Type script:
import * as functions from 'firebase-functions';
import admin = require('firebase-admin');
//the cause of an error
import * as firebase from 'firebase';
admin.initializeApp()
export const getProfilePicture = functions.https.onRequest((request, response) => {
//also there
const uid = firebase.auth().currentUser?.getIdToken
const promise = admin.storage().bucket().file('usersPfp/' + uid).getSignedUrl({
action: 'read',
expires: '03-09.2441'
})
const p2 = promise.then(GetSignedUrlResponse => {
const data = GetSignedUrlResponse[0]
return response.send({"data": data})
})
p2.catch(error =>{
console.log(error)
return response.status(500).send({"error": error})
})
})
How to fix that?
What you're doing isn't supported. The Firebase Authentication JavaScript client library isn't supported for use in backend environments like Cloud Functions.
The idea of a current user:
firebase.auth().currentUser
only makes sense in the client app where the user is signed in. It's not something that's known on the backend.
What you can do instead is send the user's ID token from your client to your function, the use the Admin SDK to verify it, then perform some actions on the user's behalf.

Node.js - javascript calling functions from javascript file

I am working on a Express/NodeJs project. I am new to Express/NodeJs, I am trying to import airportQuery.js into DistanceFormula.js. I am trying to directly import airportQuery.js from DistanceFormula.js. Im trying to call getAirports and return the answer to DistanceFormula.js. I not sure if I have to use the node routing or if i'm doing it correctly.
File Stucture:
File Structure
DistanceFormula.JS
import {getAirports} from "./api/airportQuery";
console.log(getAirports('3c675a'));
AirportQuery.js
async function getAirports(planeIcao) {
let airport = {
arrival: "",
destination: ""
};
const airport_url = 'https://opensky-network.org/api/flights/aircraft?icao24=' + planeIcao + '&begin=1517184000&end=1517270400';
const response = await fetch(airport_url);
const data = await response.json();
console.log(data[0]);
console.log(data[0].estArrivalAirport);
airport.arrival = data[0].estArrivalAirport;
console.log(data[0].estDepartureAirport);
airport.destination = data[0].estDepartureAirport;
return airport
}
const fetch = require("node-fetch");
export {getAirports};
ERROR: Uncaught SyntaxError: Cannot use import statement outside a module
To use modules in node.js, you have to do the following:
Be running a version of nodejs that supports ESM modules (v8.5+).
Run with this command line flag: node --experimental-modules
Name your file with an .mjs file extension OR specify it as a module in package.json
See the relevant documentation for more info.
This is true not only for the top level file you import, but if it also uses import, then the same rules above have to apply to it too.
Note, that once you get your modules to load properly, you will then have a problem with this line of code because getAirports() returns promise, not a value. All async functions return a promise, always. The return value in the function will become the resolved value of the returned promise. That's how async functions work. So, change this:
console.log(getAirports('3c675a'));
To this:
getAirports('3c675a').then(result=> {
console.log(result);
}).catch(err => {
console.log(err);
});

Inline import by ES6 modules in Node.js

In an "old way" of managing modules in Node.JS (CommonJS modules) you can do something like this:
Example of Express.js route: app.use('/user', require("./user"));
How to do this when I am using ES6 Modules (import, export) and transcribing by Node.JS server by babel?
I can't just do: app.use('/user', import {user} from './user');
Try separating it out into multiple expressions - import (as well as export) are not available at the same lexical level as you are trying to use it the example:
import { user } from './user'
...
app.use('/user', user)
There is a way to do dynamic inline imports in node, detailed here:
https://javascript.info/modules-dynamic-imports
This code has worked for me:
let {default: foo} = await import('./foo.js');
Here is a working example of a function I wrote as part of a db migration tool in node.
const getMigrations = async (path) => {
const migrateDir = await fs.readdirSync(path);
const migrations = await Promise.all(migrateDir.map(async (filename) => {
let {default: migration} = await import(`${path}/${filename}`);
return migration;
}));
migrations.sort((a, b) => {
return a.seq - b.seq;
});
return migrations;
};
Where an example migration is like:
export default {
seq: 1.1,
label: 'create user table',
sql: `
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
...
);
`
};
I am using node v12.18.4 with "type": "module" in my package.json. When I run the script, I get a warning that the ESM module loader is experimental, but it works. However, there is a note on the page linked to above that says:
Dynamic imports work in regular scripts, they don’t require script type="module".
I hope this helps. I believe you should be able to apply this to your problem.

import svg files inside meteor

I'm working on a project using meteor + react as front-and-back end.
For front-end UI, I am using element-react (https://eleme.github.io/element-react/#/en-US/quick-start) which is really cool and awesome. However when I tried to import element-react into my project (as instructed in the quick start of element-react homepage), meteor failed to compile static files and returned "Uncaught Error: Cannot find module './assets/error.svg''" which is the file do exist and has correct relative path.
Is there something missing or in meteor we simply can not use "require('./assets/error.svg')" to load a svg image?
According to this post in Meteor's forum.
You can use something like Meteor methods and the Assets API to get most any data from your server though. Something like
/server/main.js
Meteor.methods({
'svg.get'(data) {
return Assets.getText(data.path)
}
})
and
/client/main.js
const getSVG = async (path) => {
return await new Promise((resolve, reject) => {
Meteor.call('svg.get', { path }, (err, res) => {
if (err) reject('Something went wrong')
resolve(res)
})
})
}
const SVG = await getSVG('some/path/relative/to/private/file.svg')

How to import MongoDB using es6 style imports?

Hopefully this is a simple question. I am trying to import MongoDB using the es6 import-from style. If I import using node require it works fine.
let mongo = require('mongodb');
let MongoClient = mongo.MongoClient;
But if I import it the es6 way it breaks without errors or logs.
import {MongoClient} from 'mongodb';
But it doesn't break when compiling/running it only breaks when I try to do anything with MongoClient.
Here is my Db Manager class-
import {MongoClient} from 'mongodb';
export class DbManager {
constructor() {
console.log('Constructing DB Connection');
}
}
When I run my server I get several logs from other managers and events.
mycomputer myuser$ ./start.sh
Server Constructing
Route Manager Constructing
Initializing Route: Static
Constructing DB Connection
http server started on port: 8000
But if I do a console.log of the MongoClient there is simply no output.
import {MongoClient} from 'mongodb';
export class DbManager {
constructor() {
console.log('Constructing DB Connection');
console.log(MongoClient);
}
}
And the output looks like this-
mycomputer myuser$ ./start.sh
mycomputer myuser$
There are no compile errors so I don't understand why this isn't working. Furthermore, I don't understand why there aren't any logs! This is one of the last things that happens, there should at least be logs up until that point I'd think. If you'd like to see my start.sh script here it is (quick and dirty, don't judge me):
tsc
echo "var System = require('systemjs');" > dist/final.js
babel dist/typescript.js >> dist/final.js
echo "System.import('main');" >> dist/final.js
node dist/final.js
EDIT
Continuing to search for the answer while waiting (hoping) for a response. I'm taking a look at the resulting final.js and if MongoClient is used anywhere in the file the System.register function call looks like this-
System.register("db/db.manager", ["mongodb"] ...
And if I don't use it (even if I import it) it does not show mongodb.
System.register("db/db.manager", [] ...
That would explain why nothing would happen. Something is wrong with trying to import mongodb. Not sure yet what to do.
EDIT EDIT
Found a solution. One i'm not thrilled with but maybe it's just the way it has to be.
I don't think I can rely on es6 imports. It looks like I can use it to import the typedefs but not the actual module. How I got around this is like this-
import {Db as MongoDb, MongoClient} from 'mongodb';
let mongodb = require('mongodb');
let mongoClient: MongoClient = mongodb.MongoClient;
A lot of extra work. If there's another way please let me know.
Listen, I know there are more than a handful of cracks at this solution here. Some may work for you, but for me, none solved me but the one below.
2021 UPDATE:
BORING BACKSTORY ALERT
We're using Node v14.16.0 and our package.json has "type": "module" set. So, our code is ES6+ and commonjs imports are a deal-breaker in most cases, especially when it comes to the MongoDB Native 3.6 NodeJS Driver.
Lucky for us, MongoDB Native ^4.0.0-beta.3 is written in TypeScript, and works as expected. Prepare your shattered sprits for liftoff. ;) Oh, and rather than store your secret sauce (user:pass and uri) in your source code, check out node-config and be safe.
THE SOLUTION
# This version will keep changing after this posts, so take heed.
$ cd path/to/your/project
$ npm i -s mongodb#4.0.0-beta.3
Inside your project:
import config from 'config'
// MongoDB
import { MongoClient } from 'mongodb'
const client = new MongoClient(config.get('mongodb.uri'))
await client.connect()
const db = client.db()
const stuff = db.collection('AllTheStuff')
const record = {
type: "ThisAndThat",
lastUpdated: new Date().getTime()
}
const query = { type: "ThisAndThat" }
const options = { upsert: true }
const result = await stuff.replaceOne(query, record, options)
And now all your cats are sleep silent tonight. Hopefully this lowers the level of unchallenged insanity in the world, or helps you in your quest, whichever suits your taste in achievement. :)
import { MongoClient } from 'mongodb';
just imports type definition from node_modules/#types/mongodb/index.d.ts
import * as mongodb from 'mongodb';
imports everything from node_modules/mongodb/index.js and its the same as
let mongodb = require('mongodb');
Try this:
import { default as mongodb } from 'mongodb';
let MongoClient = mongodb.MongoClient;
Edit
As Elihu pointed out in the comment below, the additional integration of #types/mongo is now deprecated and is no longer needed as the mongo-package now comes with types per default.
npm install --save mongodb is therefore sufficient.
Original Answer
As mkalmo suggested you can import the mongodb types:
Step 1: Install via the npm mongodb types package
npm install --save #types/mongodb
Step 2: Use it!
import mongodb from "mongodb";
const MongoClient = mongodb.MongoClient;
This works for me:
import mongodb from 'mongodb'
const { MongoClient } = mongodb

Categories

Resources