undefined is not a function (evaluating '_reactNativeMeteor2.default.collection("messages").find().fetch()') - mongodb

In my Meteor app I have a collection definition like this:
this.collections.Messages = new Mongo.Collection("messages");
Now I try to connect to it from a react native meteor like this:
import React, { Component } from 'react';
import Meteor, { createContainer } from 'react-native-meteor';
import MessageListComponent from '../routes/messageList';
export default MessageListContainer = createContainer(() => {
const messagesHandle = Meteor.subscribe('userMessage');
const loading = !messagesHandle.ready();
const messages = Meteor.collection("messages").find().fetch();
return {
loading,
messages
};
}, MessageListComponent);
But it's return below red error message on device:
undefined is not a function (evaluating '_reactNativeMeteor2.default.collection("messages").find().fetch()')
What is the problem guys?

Try eliminating the fetch() from your messages const:
const messages = Meteor.collection('messages').find();
The fetch converts the cursor into an array, and probably isn't necessary here. Also, this line is the only one where you have double quotes, but I'm not sure that that is relevant.

Related

SvelteKit With MongoDB ReferenceError: global is not defined

I'm trying to setup MongoDB connection library function. I know this function is solid, its used in a whole lot of places (search for Global is used here to maintain a cached connection across hot reloads) and you'll find a whole lot of uses including next.js releases. Note, the purpose of global storage for the database connection is to reduce the overall # of db connections in use at any one time.
What I'm not understanding is the error I'm getting when I import this library via import { connectToDatabase } from '$lib/database';
database.js
// https://github.com/mongodb-developer/mongodb-next-todo/blob/main/util/mongodb.js
import { ENV_OBJ } from "$lib/env";
import { MongoClient } from "mongodb";
const uri = ENV_OBJ.MONGODB_URI;
if (!uri) {
throw new Error("Please define the Mongodb uri environment variable inside .env");
}
/**
* Global is used here to maintain a cached connection across hot reloads
* in development. This prevents connections growing exponentially
* during API Route usage.
*/
let cached = global.mongo
if (!cached) {
cached = global.mongo = { conn: null, promise: null }
}
export const connectToDatabase = async() => {
if (cached.conn) {
return cached.conn;
}
if (!cached.promise) {
const options = {
useNewUrlParser: true,
useUnifiedTopology: true
};
cached.promise = MongoClient.connect(MONGODB_URI, opts).then((client) => {
return {
client,
db: client.db(MONGODB_DB),
}
})
}
cached.conn = await cached.promise;
return cached.conn;
}
The errors:
global is not defined
ReferenceError: global is not defined
at node_modules/mongodb/lib/promise_provider.js (http://localhost:3000/node_modules/.vite/mongodb.js?v=3885e04e:548:25)
at __require2 (http://localhost:3000/node_modules/.vite/chunk-6ODJH7E3.js?v=3885e04e:10:44)
at node_modules/mongodb/lib/utils.js (http://localhost:3000/node_modules/.vite/mongodb.js?v=3885e04e:6524:30)
at __require2 (http://localhost:3000/node_modules/.vite/chunk-6ODJH7E3.js?v=3885e04e:10:44)
at node_modules/mongodb/lib/cursor/abstract_cursor.js (http://localhost:3000/node_modules/.vite/mongodb.js?v=3885e04e:10873:19)
at __require2 (http://localhost:3000/node_modules/.vite/chunk-6ODJH7E3.js?v=3885e04e:10:44)
at node_modules/mongodb/lib/index.js (http://localhost:3000/node_modules/.vite/mongodb.js?v=3885e04e:25281:29)
at __require2 (http://localhost:3000/node_modules/.vite/chunk-6ODJH7E3.js?v=3885e04e:10:44)
at http://localhost:3000/node_modules/.vite/mongodb.js?v=3885e04e:25616:23
Note, I do see a file in my generated minimal sveltekit repo called global.d.ts I'm not sure of its purpose. It contains only:
/// <reference types="#sveltejs/kit" />
Any ideas on what's causing the error?
Reference: "#sveltejs/kit": "version": "1.0.0-next.118",
Edit: After spending a whole lot of time on this issue, the global not defined error seems to come from import { MongoClient } from "mongodb"; If I add appropriate console.logs, I can see that the MongoClient function works fine on the server, but then I get the global error on the client. The server indicates no errors at all.
So it turns out I was calling import { connectToDatabase } from '$lib/database' not in a .js helper file or api style (.js) endpoints. I was attempting to use that import and make a database call directly from the <script> portion of a xxx.svelte file.
Definite no go. That generates an immediate global not defined error.

I can't access an object's properties

The next lines work fine and I can see the whole object in the console log:
Meteor.subscribe('projects')
var oneProject = Projects.findOne(key1);
console.log(oneProject)
In the console, I can see the oneProject's properties, even the name property.
Now with the following lines, the result is an error:
Meteor.subscribe('projects')
var oneProject = Projects.findOne(key1);
console.log(oneProject.name)
The error is: "Cannot read property 'name' of undefined".
This is the whole code:
import { Meteor } from 'meteor/meteor';
import { withTracker } from 'meteor/react-meteor-data';
import { Projects } from '/imports/api/projects.js';
import ProjectFormUpdate from './ProjectFormUpdate.jsx';
export default ProjectFormUpdateContainer = withTracker(({ key1 }) => {
Meteor.subscribe('projects')
var oneProject = Projects.findOne(key1);
console.log(oneProject.name)
return {
oneProject:oneProject,
};
})(ProjectFormUpdate);
A subscription in Meteor is asynchronous. This means the data is not always immediately available.
Tracker.autorun(() => {
const sub = Meteor.subscribe('projects');
if (sub.ready()){
const oneProject = Projects.findOne(key1);
console.log(oneProject.name);
}
});
will not try to find the project until the subscription is ready.

Meteor + React: Can't get data from mongoDB Collection

I have a Meteor Application that I'm developing with React. I still have the autopublish package in my project (autopublish#1.0.7).
Here is my relevant code:
MainMenu.jsx
import React, { Component, PropTypes } from 'react'
import { Meteor } from 'meteor/meteor'
import { FlowRouter } from 'meteor/kadira:flow-router'
import { createContainer } from 'meteor/react-meteor-data'
import { ChatRooms } from '/imports/api/chatrooms.js'
export class MainMenu extends Component {
render() {
console.log(this.props.chatrooms)
return (
{/* Render stuff here is not part of the scope of this question */}
)
}
}
MainMenu.PropTypes = {
chatrooms: PropTypes.array.isRequired
}
export default createContainer(() => {
return {
chatrooms: ChatRooms.find({}).fetch()
}
}, MainMenu)
chatrooms.js
import { Mongo } from 'meteor/mongo'
export const ChatRooms = new Mongo.Collection('chatrooms')
The console.log(this.props.chatrooms) in the MainMenu Component always returns an empty array ([]).
There are definitely items in the Mongo Database because when I run the meteor mongo command in my console and type db.chatrooms.find({}); it returns the 3 items that I've inserted to test this all.
Anyone have any idea what I may be doing wrong here? Help would be much appreciated!
I've figured it out. I left out a crucial step of this whole process.
In my /server/main.js file I needed to add the following line which fixed everything:
import '../imports/api/chatrooms.js

How to properly subscribe to collection on Meteor client side?

First of all, I'm not a newbie to Meteor, but after the latest Meteor updates I have to re-study the framework, and now I'm having trouble using Meteor subscription on the client side.
To be specific, I have subscribed a collection on the client side, however when I try to refer to it the browser console reported the error:
Exception in template helper: ReferenceError: Chatbox is not defined
Here's the structure of my code:
imports/api/chatbox/chatboxes.js
// define the collection
export const Chatbox = new Mongo.Collection("chatbox");
imports/api/chatbox/server/publication.js - to be imported in server/main.js
import { Meteor } from "meteor/meteor";
import { Chatbox } from "../chatboxes";
Meteor.publish("chatbox", function(parameter) {
return Chatbox.find(parameter.find, parameter.options);
});
imports/ui/chatbox/chatbox.js - page template to be rendered as content upon routing
import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';
import './chatbox.html';
import './chatbox.css';
Template.chatbox.onCreated(function bodyOnCreated() {
this.state = new ReactiveDict();
// create subscription query
var parameters = {
find: {
// query selectors
permission: "1001",
},
options: {
// query options
}
};
Meteor.subscribe("chatbox", parameters);
});
Template.chatbox.helpers({
canAddMore() {
// Chatbox collection direct access from client
return Chatbox.find().count() < 3;
},
});
I'd appreciate if you can help me with this issue. Thanks all for taking your time reading my question!
Regards
You need to import Chatbox in imports/ui/chatbox/chatbox.js:
import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';
import { Chatbox } from "../chatboxes"; // correct this path
It's undefined right now because it hasn't been imported.

Not able to encrypt a string with a public key in Protractor

I am trying call the encrypt function mentioned below:
var encryptor = require("./jsencrypt.js");
this.encrypt = function () {
var key="LxVtiqZV6g2D493gDBfG0BfV6sAhteG6hOCAu48qO00Z99OpiaIG5vZxVtiqZV8C7bpwIDAQAB";
encryptor = new JSEncrypt();
encryptor.setPublicKey(key);
var newString = encryptor.encrypt('Password');
console.log("Encrypted password =",newString);
}
Initially I was getting Reference Error for undefined JSEncrypt.
So I downoaded jsencrypt.js file and added var encryptor = require("./jsencrypt.js");at the begining. Now I am getting following error:
Message:
ReferenceError: navigator is not defined
Stacktrace:
ReferenceError: navigator is not defined
at e:\Praveen Data\Projects\ECP\CentralRegistryUI\TestScripts\Utils\jsencrypt.js:73:13
at Object.<anonymous> (e:\Praveen Data\Projects\ECP\CentralRegistryUI\TestScripts\Utils\jsencrypt.js:4342:3)
at require (module.js:385:17)
Tried using windows.navigator in jsencrypt.js, but didn't work.
Protractor tests are not run in browser environment but in node.js, because of that navigator object is not available there. JSEncrypt relies on it to work on the client side across different browsers and versions.
It's referenced in many places in the JSEncrypt code so my best bet would be to either switch to a server side encryption library that would work for you or if not possible mock a global navigator json object with all expected properties/methods as if it was a Chrome browser - node.js runs on chrome's js engine so should work fine.
One of my colleague helped me with the solution.
So here I have a function for encryption:
this.initializeEncryptedPassword = () => {
//console.log("before calling encrypt... ");
browser.executeScript(() => {
//console.log("Starting to return encryptor...");
return window.loginEncryptor.encrypt(window.loginPassword);
}).then((encryptedPassword) => {
this.encryptedPassword = encryptedPassword;
});
//console.log("after calling encrypt...");
}
This function is being called by:
export default class Encryptor {
constructor($window, $http) {
'ngInject';
this.encryptor = new $window.JSEncrypt();
//Need to use HTTP here instead of resource since the resource does not return plain text.
//Getting Public Key by hitting a rest uri.
$http({method: "GET", url: "/xyz/authenticate"}).success((item) => {
this.encryptor.setPublicKey(item);
//set the current encryptor on the window so that testing can use it
$window.loginEncryptor = this.encryptor;
});
}
encryptPassword(credentials) {
credentials.password = this.encryptor.encrypt(credentials.password);
}
}
Hope this help others.
before require('jsencrypt') you can write first:
const { JSDOM } = require('jsdom');
const jsdom = new JSDOM('<!doctype html><html><body></body></html>');
const { window } = jsdom;
global.window = window;
global.document = window.document;
global.navigator ={userAgent: 'node.js'};
const { JSEncrypt } = require('jsencrypt')
You can mock by doing the following:
global.navigator = { appName: 'protractor' };
global.window = {};
const JSEncrypt = require('JSEncrypt').default;