Node xmlbuilder mod TypeError: Converting circular structure to JSON - node.js

I'm trying to use the node xmlbuilder module, and copied / pasted their code from here but I get a
Converting circular structure to JSON error.
I have no clue why this is happening, here is the code:
Route:
app.get('/api/qb', function(req, res) {
qbwc.test(req, function(result){
res.send(result);
});
});
Module:
exports.test = function(data, next) {
var obj = {
person: {
name: "John",
'#age': 35,
address: {
city: "Istanbul"
},
phone: [
{
'#text': "555-1234",
'#type': 'home'
}, {
'#text': "555-1235",
'#type': 'mobile'
}
],
id: function() {
return 42;
}
}
};
var root = builder.create(obj);
return next(root);
}
EDIT:
I also tried it with something very simple to test, same issue:
var obj = { name: 'smith'};
var root = builder.create(obj);
return next(root);

Ok so after a lot of hair pulling, it seems you need to call .end() on the process, I have no idea why they don't have this in the example.
Here is what you need to do:
...
var root = builder.create(obj);
root = root.end({pretty: false});
return next(root);

Related

Error: "Missing initializer in const declaration" plaid api create link token

I'm trying to setup the plaid api in my node.js code and I need to be able to make a request for the create_link_token. The sample code from their docs is as follows:
const request: LinkTokenCreateRequest = {
user: {
client_user_id: 'user-id',
},
client_name: 'Plaid Test App',
products: ['auth', 'transactions'],
country_codes: ['US'],
language: 'en',
webhook: 'https://sample-web-hook.com',
redirect_uri: 'https://domainname.com/oauth-page.html',
account_filters: {
depository: {
account_subtypes: ['DepositoryAccountSubtype.Checking, DepositoryAccountSubtype.Savings'],
},
},
};
try {
const response = await plaidClient.linkTokenCreate(request);
const linkToken = response.data.link_token;
} catch (error) {
// handle error
}
my code is:
app.post('/api/create_link_token', async (req, res, next) => {
const request: LinkTokenCreateRequest = {
user: {
client_user_id: 'user-id',
},
client_name: 'Plaid Test App',
products: ['auth', 'transactions'],
country_codes: ['US'],
language: 'en',
webhook: 'https://sample-web-hook.com',
redirect_uri: 'https://domainname.com/oauth-page.html',
account_filters: {
depository: {
account_subtypes: ['DepositoryAccountSubtype.Checking, DepositoryAccountSubtype.Savings'],
},
},
};
try {
const response = await plaidClient.linkTokenCreate(request);
const linkToken = response.data.link_token;
} catch(e) {
handleError(e);
}
});
Right off the bat I get the error: 'LinkTokenCreateRequest' refers to a value, but is being used as a type here. Did you mean 'typeof LinkTokenCreateRequest'?ts(2749) as a red underline underneath LinkTokenCreateRequest. Side note I've never used TS before this, but I believe I have to use it on this project because some of their components require it. If I do as they suggest and change it to typeof LinkTokenCreateRequest = {... then the red underline error goes away, however upon starting the server I get the error:
const request: typeof LinkTokenCreateRequest = {
^^^^^^^
SyntaxError: Missing initializer in const declaration
I've very confused as to how I can make this work so any suggestions would be much appreciated.

I am getting a 500 response. Is the way I am trying this wrong? Or is there something I'm missing?

I'm making a game project. I have everything working to where you can create a character, and it posts okay to the database, and I can see the characters I've created on an endpoint with all the details included.
Where it doesn't work anywhere else is where I have things shifted from a context state to a separate context state for a 'character sheet' state. All the data successfully goes to my character sheet, and console.logs support everything is properly showing up, but it won't post to my url.
My model:
const mongoose = require("mongoose"),
Schema = mongoose.Schema;
const characterSheetSchema = new Schema({
characterPowers: {},
characterInventory: {},
characterArmor: {},
characterShield: {},
characterWeapon: {},
characterCoin: {},
characterHp: {},
characterStats: {},
characterExperience: { type: Number },
characterRace: {},
characterClass: {},
characterAge: {
type: Number,
},
characterName: {
type: String,
},
characterDescription: {
type: String,
},
characterLevel: { type: Number },
});
module.exports = CharacterSheet = mongoose.model(
"charactersheet",
characterSheetSchema
);
My routes:
const router = require('express').Router()
const CharacterSheet = require('../../models/chracterSheet/characterSheet.model')
router.post("/createcharactersheet", (req, res) => {
try {
let {
characterPowers,
characterInventory,
characterArmor,
characterShield,
characterWeapon,
characterCoin,
characterHp,
characterStats,
characterExperience,
characterRace,
characterClass,
characterAge,
characterName,
characterDescription,
characterLevel
} = req.body
const newCharacterSheet = new CharacterSheet({
characterPowers,
characterInventory,
characterArmor,
characterShield,
characterWeapon,
characterCoin,
characterHp,
characterStats,
characterExperience,
characterRace,
characterClass,
characterAge,
characterName,
characterDescription,
characterLevel
})
const savedCharacterSheet = newCharacterSheet.save()
res.json(savedCharacterSheet)
} catch (err) {
res.status(500).json({err: err.message})
}
})
router.get('/viewcharactersheets', (req, res) => {
CharacterSheet.find({}, function(err, charactersheets) {
if (err) {
console.log(err)
} else {
return res.json({charactersheets: charactersheets})
}
})
})
module.exports = router
My post request:
Axios.post("http://localhost:5000/characters/createcharactersheet", {
characterPowers: characterSheet.characterPowers,
characterInventory: characterSheet.characterInventory,
characterArmor: characterSheet.characterArmor,
characterShield: characterSheet.characterShield,
characterWeapon: characterSheet.characterWeapon,
chacterCoin: characterSheet.characterCoin,
characterHp: characterSheet.characterHp,
characterStats: characterSheet.characterStats,
characterExperience: characterSheet.characterExperience,
characterRace: characterSheet.characterRace,
characterClass: characterSheet.characterClass,
characterAge: characterSheet.characterAge,
characterName: characterSheet.characterName,
characterDescription: characterSheet.characterDescription,
characterLevel: characterSheet.characterLevel,
});
My Terminal
My error
POST error
Uncaught in promise error
Everything else works and goes into my restful api, but for a reason unknown to me, it won't post to my createcharactersheet document or api.
Any insight would be appreciated.
Mongoose Model.save() returns an Promise to try to use async/await
async/await way:
router.post("/createcharactersheet", async(req, res) => {
...
try {
const newCharacterSheet = new CharacterSheet({
...
})
await newCharacterSheet.save()
res.status(201).json(newCharacterSheet)
} catch (error) {
res.status(500).send(e.message)
{
})
or (im not sure)
const savedCharacterSheet = newCharacterSheet.save()
savedCharacterSheet
.then(saved =>
res.json(saved)
)
.catch(e =>
res.status(500).send(e.message)
)
Edit
Aslo log you errors
catch (e) {
console.error(e)
}

Mock multiple api call inside one function using Moxios

I am writing a test case for my service class. I want to mock multiple calls inside one function as I am making two API calls from one function. I tried following but it is not working
it('should get store info', async done => {
const store: any = DealersAPIFixture.generateStoreInfo();
moxios.wait(() => {
const request = moxios.requests.mostRecent();
request.respondWith({
status: 200,
response: store
});
const nextRequest = moxios.requests.at(1);
nextRequest.respondWith({
status: 200,
response: DealersAPIFixture.generateLocation()
});
});
const params = {
dealerId: store.dealerId,
storeId: store.storeId,
uid: 'h0pw1p20'
};
return DealerServices.retrieveStoreInfo(params).then((data: IStore) => {
const expectedOutput = DealersFixture.generateStoreInfo(data);
expect(data).toMatchObject(expectedOutput);
});
});
const nextRequest is always undefined
it throw error TypeError: Cannot read property 'respondWith' of undefined
here is my service class
static async retrieveStoreInfo(
queryParam: IStoreQueryString
): Promise<IStore> {
const res = await request(getDealerStoreParams(queryParam));
try {
const locationResponse = await graphQlRequest({
query: locationQuery,
variables: { storeId: res.data.storeId }
});
res.data['inventoryLocationCode'] =
locationResponse.data?.location?.inventoryLocationCode;
} catch (e) {
res.data['inventoryLocationCode'] = 'N/A';
}
return res.data;
}
Late for the party, but I had to resolve this same problem just today.
My (not ideal) solution is to use moxios.stubRequest for each request except for the last one. This solution is based on the fact that moxios.stubRequest pushes requests to moxios.requests, so, you'll be able to analyze all requests after responding to the last call.
The code will look something like this (considering you have 3 requests to do):
moxios.stubRequest("get-dealer-store-params", {
status: 200,
response: {
name: "Audi",
location: "Berlin",
}
});
moxios.stubRequest("graph-ql-request", {
status: 204,
});
moxios.wait(() => {
const lastRequest = moxios.requests.mostRecent();
lastRequest.respondWith({
status: 200,
response: {
isEverythingWentFine: true,
},
});
// Here you can analyze any request you want
// Assert getDealerStoreParams's request
const dealerStoreParamsRequest = moxios.requests.first();
expect(dealerStoreParamsRequest.config.headers.Accept).toBe("application/x-www-form-urlencoded");
// Assert graphQlRequest
const graphQlRequest = moxios.requests.get("POST", "graph-ql-request");
...
// Assert last request
expect(lastRequest.config.url).toBe("status");
});

backbone.js and express: trouble searching a mongodb collection by field with a query string

I am new to backbone, express, and mongodb.
I am trying to pass a query string to search a mongodb collection by field.
I am doing something wrong. If I comment out the "fetch" from my router, the page is found.
If I try to fetch, then I get a page not found error.
I've tried to isolate where it's breaking, but the backbone architecture is still confusing to me. Thanks in advance. (I'm betting it's a syntax issue in my mongodb call)
kristin
Here is my code.
this URL should return a collection where "type" = 3.
localhost:8888/#content/3
model/models.js:
window.Content = Backbone.Model.extend({
urlRoot: "/content",
idAttribute: "_id"
});
window.ContentCollection = Backbone.Collection.extend({
model: Content,
url: "/content"
});
views/content.js
window.ContentListView = Backbone.View.extend({
initialize: function () {
this.render();
},
render: function () {
//return this;
this.$el.append('<ul class="thumbnails">');
this.collection.each(function(model) {
this.$('.thumbnails').append(new ContentView({model: model}).render().el);
}, this);
return this;
} });
window.ContentView = Backbone.View.extend({
tagName: "li",
initialize: function () {
this.model.bind("change", this.render, this);
this.model.bind("destroy", this.close, this);
},
render: function () {
$(this.el).html(this.template(this.model.toJSON()));
return this;
}
});
views/main.js
var AppRouter = Backbone.Router.extend({
routes: { "content/:type" : "contentType" },
contentType: function(type) {
var contentList = new ContentCollection({type : type});
contentList.fetch({success: function(){
$("#content").empty().append(new ContentListView({collection: contentList}).el);
}});
this.headerView.selectMenuItem('build-menu');
},
utils.loadTemplate([
'ContentView'
], function() {
app = new AppRouter();
Backbone.history.start(); });
contentView.html
name (<% tag won't print here)
routes/modules.js
exports.findContentByType = function(req, res) {
var type = req.params.type;
db.collection('content', function(err, collection) {
collection.find({'type': type.toString()}).toArray(function(err, items) {
res.send(items);
});
});
};
server.js
app.get('/content/:type', module.findContentByType);
I can see a couple of problems here:
this.headerView.selectMenuItem('build-menu'); (in the router) implies you've defined headerView in the router object, but it's not defined.
Similarly, this.template inside ContentView is not defined
When I remove the line in #1, and and define a dummy template in ContentView:
template: _.template("<div> Test: <%= version %> </div>"),
Then the view at least renders -- see here. (This is with dummy data -- I can't confirm that your server is returning valid/expected JSON.)

populating menus from multiple collections

I'm new to backbone.js and express and I have been adapting Christophe Coenraets Wine Cellar REST API example application for my own project.
I am building a form that has several menus needing to be populated from multiple unrelated collections in mongodb.
I am able to populate one menu with one collection, but I have no idea how to get more than one collection to my form View.
Here are the files I am using to populate one menu. How do I expand this to populate two menus?
I suppose I could make a new View for every menu I want to populate - but that seems like overkill.
Can I combine two mongodb find() collections into one object, and list them separately on a page? If so, how?
thanks in advance!
/routes/modules.js contains:
exports.findAllModules = function(req, res) {
db.collection('modules', function(err, collection) {
collection.find().toArray(function(err, items) {
res.send(items);
});
});
};
/server.js contains:
app.get('/modules', module.findAllModules);
/public/js/main.js contains:
routes: {
"modules" : "list" }
...
list: function(page) {
var p = page ? parseInt(page, 10) : 1;
var moduleList = new ModuleCollection();
moduleList.fetch({success: function(){
console.log('in list function');
$("#content").html(new ModuleListView({model: moduleList, page: p}).el);
}});
this.headerView.selectMenuItem('home-menu');
},
...
utils.loadTemplate([
'ModuleListItemView' ], function() {
app = new AppRouter();
Backbone.history.start(); });
/public/models/models.js contains:
window.Module = Backbone.Model.extend({
urlRoot: "/modules",
idAttribute: "_id",
initialize: function () {
this.validators = {};
this.validators.name = function (value) {
return value.length > 0 ? {isValid: true} : {isValid: false, message: "You must enter a name"};
};
validateItem: function (key) {
return (this.validators[key]) ? this.validators[key](this.get(key)) : {isValid: true};
},
validateAll: function () {
var messages = {};
for (var key in this.validators) {
if(this.validators.hasOwnProperty(key)) {
var check = this.validators[key](this.get(key));
if (check.isValid === false) {
messages[key] = check.message;
}
}
}
return _.size(messages) > 0 ? {isValid: false, messages: messages} : {isValid: true};
},
defaults: {
_id: null,
name: ""
} });
window.ModuleCollection = Backbone.Collection.extend({
model: Module,
url: "/modules"
});
/public/js/views/modulelist.js contains:
window.ModuleListView = Backbone.View.extend({
initialize: function () {
this.render();
},
render: function () {
var modules = this.model.models;
$(this.el).html('<ul class="thumbnails"></ul>');
for (var i = 0; i < modules.length; i++) {
$('.thumbnails', this.el).append(new ModuleListItemView({model: modules[i]}).render().el);
}
return this;
} });
window.ModuleListItemView = Backbone.View.extend({
tagName: "li",
initialize: function () {
this.model.bind("change", this.render, this);
this.model.bind("destroy", this.close, this);
},
render: function () {
$(this.el).html(this.template(this.model.toJSON()));
return this;
} });
/public/tpl/ModuleListView.html contains:
Not entirely sure how your code works, but here are a few backbone tips.
If you wanna build a menu from a collection don't pass the collection as a model.
Instead of:
$("#content").html(new ModuleListView({model: moduleList, page: p}).el);
Use:
$("#content").empty().append(new ModuleListView({collection: moduleList, page: p}).el);
Instead of:
render: function () {
var modules = this.model.models;
$(this.el).html('<ul class="thumbnails"></ul>');
for (var i = 0; i < modules.length; i++) {
$('.thumbnails', this.el).append(new ModuleListItemView({model: modules[i]}).render().el);
}
return this;
}
Use:
render: function () {
this.$el.html('<ul class="thumbnails">');
this.collection.each(function(model) {
this.$('.thumbnails').append(new ModuleListItemView({model: model}).render().el);
}, this);
return this;
}
If you have no need in updating or deleting your models, it's enough to add the url path /modules only to the collection, for reading the initial modules.

Resources