I'm working with class 'State', it has a model and controller file. However, when importing these classes on my main (app.js), there seem to be a clash as 'state.model.js' is 'required' both in app.js and state.controller.js. Thus, giving me the error, State is not a constructor.
app.js:
const State = require('./model/state.model');
const stateController = require('./controller/state.controller');
stateController.insert(msg, State.STATE_REMINDER.name, State.STATE_REMINDER.key.day, selected_day, (err, doc) => {
if (err) throw err;
console.log("[STATE][INSERT]", doc);
});
state.controller.js:
const Database = require('../database');
const State = require('../model/state.model');
const db = Database.collection('states');
db.loadDatabase((err) => {
if (err) throw err;
console.log("[STATES] Database connected");
});
exports.insert = (msg, state, key, value, callback) => { // msg refers to Telegram Callback
let insertState = new State(undefined, msg.from.id, msg.chat.id, state, key, value);
console.log(insertState);
db.insert(insertState, (err, newDoc) => {
if (err) throw err;
callback(err, newDoc);
});
};
state.model.js:
const stateController = require('../controller/state.controller');
const STATE_REMINDER = {
name: "STATE_REMINDER",
key: {
day: "DAY",
time: "TIME"
}
};
class State {
constructor(id, user_id, chat_id, state, key, value) {
this._id = id;
this.user_id = user_id;
this.chat_id = chat_id;
this.state = state;
this.key = key;
this.value = value;
this.timestamp = new Date();
}
static get STATE_REMINDER() {
return STATE_REMINDER;
}
}
module.exports = State;
This problem is actually fixed when i swap the order of codes in app.js to:
const stateController = require('./controller/state.controller');
const State = require('./model/state.model');
Why is that so? Any help is appreciated. Thanks!
Your code has a circular dependency loop:
app.js requires state.model.js which requires state.controller.js which requires state.model.js which requires state.controller.js etc etc
In this case, require will detect a circular dependency and will NOT go on forever. However this means at some point it will just return "null" instead of the actual class. It probably will look like this:
app.js -> requires state.model.js
state.model.js -> requires state.controller.js
state.controller.js -> requires state.model.js. At this point node detects the circular looop and will return null for state.model.js, then will begin to unwind the stack.
I'm not sure why it would work when you switch the order, the loop is still there and should be causing an issue still, probably some oddity in how node is importing the files.
Related
I'm new to nextjs and I'm creating API on next.js to perform db update using the pg-promise. However, it always hit the WARNING: Creating a duplicate database object for the same connection on console when the app is calling the API.
I tried browsing the docs but couldn't find a solution. I also tried solution (update-2) mentioned on stackoverflow page below, but the warning still exists.
Where should I initialize pg-promise
I think the problem is on the method I used to set the columnset. However I can't find proper way to do it. How should I fix it with pg-promise ?
Db setting code:
import ConfigEnv from 'utils/configuration';
import * as pgLib from 'pg-promise';
const initOptions = {
capSQL: true,
};
const pgp = require('pg-promise')(initOptions);
interface IDatabaseScope {
db: pgLib.IDatabase<any>;
pgp: pgLib.IMain;
}
export function createSingleton<T>(name: string, create: () => T): T {
const s = Symbol.for(name);
let scope = (global as any)[s];
if (!scope) {
scope = {...create()};
(global as any)[s] = scope;
}
return scope;
}
export function getDB(): IDatabaseScope {
return createSingleton<IDatabaseScope>('my-app-db-space', () => {
return {
db: pgp(ConfigEnv.pgp),
pgp
};
});
}
API code:
import {getDB} from 'db/pgpdb';
const {db, pgp} = getDB();
const cs = new pgp.helpers.ColumnSet([
'?detail_id',
'age',
'name'
// 'last_modified_date',
], {
table: 'user_detail',
})
export default async (req, res) => {
try {
// generating the update query where it is needed:
const update = pgp.helpers.update(req.body.content, cs) + ` WHERE v.detail_id = t.detail_id`;
// executing the query
await db
.none(update)
.then(() => {
return res.status(200).end();
})
.catch((error) => {
console.log('error', error);
return res.status(500).send(error);
});
} catch (error) {
console.log(error);
}
};
The original error say's: Cannot destructure property 'firstime' of 'undefined' or 'null'.
I am developing web-base desktop application for Windows pc using node.js and Electron.
I am trying to persist some data in user data directory, I found the idea and using the same approach in this link.
Writing and fetching data works fine, however the error occurred at the first time of fetching the data.
here is the code for UserPreferences class
const electron = require('electron');
const path = require('path');
const fs = require('fs');
class UserPreferences {
constructor(opts) {
const userDataPath = (electron.app || electron.remote.app).getPath('userData');
this.path = path.join(userDataPath, opts.configName + '.json');
this.data = parseDataFile(this.path, opts.defaults);
console.log(userDataPath);
}
get(key) {
return this.data[key];
}
set(key, val) {
this.data[key] = val;
fs.writeFileSync(this.path, JSON.stringify(this.data));
}
}
function parseDataFile(filePath, defaults) {
try {
return JSON.parse(fs.readFileSync(filePath));
} catch (error) {
return defaults;
}
}
module.exports = UserPreferences;
and here's the function for using the UserPreferences class
function isFirstTime() {
try{
const userAccount = new UserPreferences({
configName: 'fipes-user-preferences', // We'll call our data file 'user-preferences'
defaults: {
user: { firstime: true, accountid: 0, profileid: '' }
}
});
var { firstime, accountid, profileid } = userAccount.get('user');
if (firstime === true) { //check if firstime of running application
//do something
} else {
//do something
}
}catch(err){
console.log(err.message);
}
}
the error occurred on the line where I am checking weather the firstime is true or false.
First of all do not declare a object like var { firstTime, .. } like this. if you do this firstTime will be a property of an anonymous object. That you can never access elsewhere. Check what is the output of userAccount.get('user') function, output contain some object like { firstime: true, accountid: "test", profileid: "test" } then try this. Hope this helps you.
var result=userAccount.get('user');
if(result.firstTime===true){
//your code
}
Here is a version of UserPreferences which will be more natural to use as you write your code. You can create it like you see in isFirstTime.
console.debug(userPreferences[accountId]);
userPreferences[accountId] = 1;
This is preferred because there is no reason for a developer not to treat UserPreferences as an object. Another good idea would be separating the writing to the file into a separate flush method, in case you are updating preferences often.
const electron = require("electron");
const fs = require("fs");
const path = require("path");
class UserPreferences {
constructor(defaultPrefs, pathToPrefs) {
const app = electron.app || electron.remote.app;
this.pathToPrefs = path.join(app.getPath("userData"), pathToPrefs + ".json");
try {
this.store = require(this.pathToPrefs);
}
catch (error) {
this.store = defaultPrefs;
}
return new Proxy(this, {
get(target, property) {
return target.store[property];
},
set(target, property, value) {
target.store[property] = value;
fs.writeFileSync(target.pathToPrefs, JSON.stringify(target.store));
}
});
}
}
module.exports = UserPreferences;
Here is a pure version of isFirstTime, that should do what you want, while maintaining a more robust method of checking for isFirstTime. The check can also be changed so check whether lastSignIn is equal to createdAt (with appropriate defaults, of course).
function isFirstTime() {
const account = new UserPreferences({
user: {
accountId: 0,
createdAt: new Date(),
lastSignIn: null,
profileId: ""
}
}, "fipes-user-preferences");
const {lastSignIn} = account;
return lastSignIn === null;
}
I'm building a GraphQL Server where I need to do some sort of validation before committing data to database (MongoDB and Mongoose).
One of these checks is related to unique fields. So, a model may have one or more unique fields and I need to be able to check for that before saving into database.
So, I have build some helper functions to do it and the code is below:
Helper code:
import mongoose from "mongoose";
const isFieldUnique = (modelName, fieldName, fieldValue) => {
let model = mongoose.model(modelName);
let query = {};
query[fieldName] = fieldValue;
return model.findOne(query).exec();
};
const executeUniquePromises = (uniques, modelName, data) => {
let promises = [];
uniques.map(name => {
let value = data[name];
if (!value)
throw new Error("Cannot test uniqueness for a null field.");
promises.push(
isFieldUnique(modelName, name, value)
.then(value => {
if (value) {
let error = name + ' is not unique';
console.log(error);
return error;
}
console.log(name + ' is unique');
return null;
})
.catch(error => {
throw new Error(error);
})
)
});
return Promise.all(promises);
};
export const checkUniqueness = (uniques, modelName, data) => {
return new Promise((resolve, reject) => {
executeUniquePromises(uniques, modelName, data).then(result => {
let errors = [];
// Check for errors
result.map((error) => {
if (error)
errors.push(error);
});
if (errors.length > 0)
return reject(errors);
else
resolve();
});
});
}
Mongoose static create function:
import * as helper from './helper';
schema.statics.create = function (data) {
let uniques = ['name', 'email'];
helper.checkUniqueness(uniques,'Company', data)
.then(result => {
let user = new this(data);
return company.save();
})
.catch(error => {
throw new Error(error);
});
}
GraphQL code:
const createUser = {
type: UserType,
description: "Create a user",
args: {
data: {
name: "user",
type: new GraphQLNonNull(UserInputType)
}
},
resolve(root, args) {
return UserModel.create(args.data);
}
};
The helper code seens to be confused and I´m not using my usage of promises with other promises are the correct way of doing it.
Remember that I may need to check several fields for uniqueness, so that is why I´ve created the promise array.
One problem is that when I´m inserting data where there are not uniques matching I get no return in my GraphQL Server.
I want to find out a better way of doing it and discover why I´m not getting back the saved object.
MongoDB already handles unique out of the box. Set the field to unique: true in the Mongoose schema. You can use mongoose-beautiful-unique to make the error messages similar to the validation error messages. And finally, read this when you can't get unique: true to work.
how do I update the ui with a new item in relay modern?
I have all other CRUD working and but can't figure out the updater on commit mutation for a new item. When I refresh the page it there. All examples use viewer object which I don't have one in my schema.
schema.graphql
type Note {
id: String
avatar: String
message: String
date: String
}
create_mutation.js
export function createMutation({ mutation, variables, environment, create }) {
const fragment = mutation().fragment;
const operation = fragment.selections[0].name;
const mutationName = fragment.name;
const type = fragment.selections[0].concreteType;
const id = 'client:${operation}:${cuid()}';
const config = {
mutation,
variables,
optimisticUpdater: proxyStore => {
// 1. Create mock record that to be added to the store
const record = proxyStore.create(id, type);
Object.keys({ ...variables, id }).forEach(key =>
record.setValue(key, `${key}`)
);
const viewerProxy = proxyStore.get(operation);
const connection = ConnectionHandler.getConnection(record, mutationName);
if (connection) {
ConnectionHandler.insertEdgeAfter(viewerProxy, record);
}
},
updater: proxyStore => {},
onError: error => console.log(error)
};
commitMutation(environment, config);
}
I have the following case, when deleting any data, I need to delete the app badges (at the moment I delete them using silent push notication and reduce the app badges number with the cloud function) if the user who sent the request has deleted. But since the user who deleted could send several requests to different users in different places, so I decided that I need to create a function that will be called in firebase database trigger functions and also it will help not to duplicate the same code everywhere .
The function will be approximate such
function adminRemoveAppBadge(userID, dataID, categoryID) {
};
And for example, call it in this function
module.exports = functions.database.ref('/cards/{cardID}/interestedUsers/{interestedUserID}').onWrite(event => {
const currentData = event.data.current;
const prevData = event.data.previous;
const cardID = event.params.cardID;
const interestedUserID = event.params.interestedUserID;
if (currentData.val() && !prevData.val()) {
// value created
return console.log('cardInterestedUserHandler - created');
} else if (!currentData.val() && prevData.val()) {
// value removed
console.log('cardInterestedUserHandler - removed', currentData.val());
const cardRef = admin.database().ref("cards").child(cardID);
const cardRefPromise = cardRef.once("value", function(snap, error) {
if (error) {
return error;
};
if (snap.val()) {
const cardJSON = snap.val();
const cardOwnerID = cardJSON["ownerID"];
if (cardOwnerID) {
const cardOwnerAppBadgesRef = admin.database().ref("userAppBadges").child(cardOwnerID).child("appBadgeModels").orderByChild("dataID").equalTo(cardID);
const cardOwnerAppBadgesRefPromise = cardOwnerAppBadgesRef.once("value", function (cardOwnerAppBadgesRefSnap, error) {
if (error) {
return error;
};
if (cardOwnerAppBadgesRefSnap.val()) {
var deletingPromises = [];
cardOwnerAppBadgesRefSnap.forEach(function(cardOwnerAppBadgesRefSnapChild) {
const appBadgeModelJSON = cardOwnerAppBadgesRefSnapChild.val();
const appBadgeModelID = appBadgeModelJSON["id"];
const senderID = appBadgeModelJSON["senderID"];
if (appBadgeModelID && senderID) {
if (senderID == interestedUserID) {
const cardOwnerAppBadgeRef = admin.database().ref("userAppBadges").child(cardOwnerID).child("appBadgeModels").child(cardOwnerAppBadgeModelID);
const cardOwnerAppBadgeRefPromise = cardOwnerAppBadgeRef.remove();
deletingPromises.push(cardOwnerAppBadgeRefPromise);
// to call
adminRemoveAppBadge
};
} else {
console.log("cardOwnerAppBadgeModelID == null");
};
});
return Promise.all(deletingPromises);
};
});
return Promise.all([cardOwnerAppBadgesRefPromise]);
} else {
return console.log("owner id == null");
};
};
});
return Promise.all([cardRefPromise]);
} else {
return console.log('cardInterestedUserHandler - updated');
};
});
Also functions are in different files. How can I call it in other firebase cloud functions and how do I deploy this function?
Update I tried to do so one of the options as written here and here, but when I tried to do deploy I got an error Cannot find module 'AppBadges/adminRemoveAppBadge.js'.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
exports.adminRemoveAppBadge = function (userID, dataID, categoryID) {
console.log("adminRemoveAppBadge nil");
};
Requested this function so
var adminRemoveAppBadgeModule = require("AppBadges/adminRemoveAppBadge.js");
and call this functions so
adminRemoveAppBadgeModule.adminRemoveAppBadge(cardOwnerID, cardID, 0);
Google Functions are just JS - so normal routes to include code work.
I place my "library" functions in a folder /lib
So my functions folder looks like this:
/functions
/lib
BuildImage.js
SendEmail.js
index.js
package.json
...etc...
within my index.js I just include my code:
const SendMail = require('./lib/SendMail')
const sendMail = new SendMail({
database: db,
mailgun: mailgun
})
exports.sendContactUsMessage = functions.database.ref('/contact-messages/{itemId}').onWrite(sendMail.send(event))
EDIT Added /lib/SendMail.js code:
module.exports = class SendMail {
constructor(config) {
if (!config) {
throw new Error ('config is empty. Must pass database and mailgun settings')
}
if (!config.database) {
throw new Error('config.database is empty. Must pass config.database')
}
if (!config.mailgun) {
throw 'config.mailgun is empty. Must pass config.mailgun'
}
this.database = config.database
this.mailgun = config.mailgun
}
sendEmail (emailData) {
return new Promise((resolve, reject) => {
this.mailgun.messages().send(emailData, (error, body) => {
if (error) {
if (debug) {
console.log(error)
}
reject(error)
} else {
if (debug) {
console.log(body)
}
resolve(body)
}
})
})
}
...
}