I'm trying to overwrite the default error messages from loopback. That's how i'm doing:
server/middleware.json:
{
"initial:before": {
"loopback#favicon": {}
},
"initial": {
"compression": {},
"cors": {
"params": {
"origin": true,
"credentials": true,
"maxAge": 86400
}
},
"helmet#xssFilter": {},
"helmet#frameguard": {
"params": [
"deny"
]
},
"helmet#hsts": {
"params": {
"maxAge": 0,
"includeSubdomains": true
}
},
"helmet#hidePoweredBy": {},
"helmet#ieNoOpen": {},
"helmet#noSniff": {},
"helmet#noCache": {
"enabled": false
}
},
"session": {},
"auth": {},
"parse": {},
"routes": {
"loopback#rest": {
"paths": [
"${restApiRoot}"
]
}
},
"files": {},
"final": {
"loopback#urlNotFound": {}
},
"final:after": {
"loopback#errorHandler": {},
"errorHandler": {}
}
}
server/middleware/error-handler.js:
module.exports = (error, req, res, next) => {
console.log('a')
};
Before overwrite, i need first intercept the error message, but i'm not getting how...
Thanks!
You can access your error message and overwrite it as below
module.exports = (error, req, res, next) => {
console.log(error.message); // logs out original error message
error.message = 'Your Custom Error message'; // this will overwrite the error message
next(error); // this is important
};
Other properties of the error object are
statusCode, name, stack
& also
details, messages if applicable
Related
I am querying the Imgix Management API with no issue. I can retrieve an individual asset and a list of assets. However, most of the data properties are null. It looks like this:
{
"data": {
"attributes": {
"analyzed_content_warnings": null,
"analyzed_faces": null,
"analyzed_tags": null,
"categories": null,
"color_model": null,
"color_profile": null,
"colors": null,
"content_type": "image/jpeg",
"custom_fields": null,
"date_created": 1667935028,
"date_modified": null,
"description": null,
"dpi_height": null,
"dpi_width": null,
"face_count": null,
"file_size": 1016205,
"has_frames": null,
"media_height": null,
"media_kind": "IMAGE",
"media_width": null,
"name": null,
"origin_path": "/test/roses.jpeg",
"source_id": "XXXXXXXXXXXXXXXXXXXX",
"tags": null,
"uploaded_by": null,
"uploaded_by_api": false,
"warning_adult": null,
"warning_medical": null,
"warning_racy": null,
"warning_spoof": null,
"warning_violence": null
},
"id": "XXXXXXXXXXXXXXXXXXX/test/roses.jpeg",
"type": "assets"
},
"included": [],
"jsonapi": {
"version": "1.0"
},
"meta": {
"authentication": {
"authorized": true,
"clientId": null,
"mode": "PUBLIC_APIKEY",
"modeTitle": "Public API Key",
"tag": "XXXXXXXXXXXXXXX",
"user": null
},
"server": {
"commit": "7c78ee15",
"status": {
"healthy": true,
"read_only": false,
"tombstone": false
},
"version": "3.187.0"
}
}
}
I'm missing data.colors, data.media_height, data.media_width.
My code is very basic:
import fetch from 'node-fetch'
const imgix_key = 'xxxxxxxx'
const imgix_source_id = 'xxxxxxxx'
const imgix_url = `https://api.imgix.com/api/v1/assets/${imgix_source_id}/test/roses.jpeg`
async function init() {
const method = 'get'
const headers = {
Authorization: `Bearer ${imgix_key}`,
'Content-Type': 'application/x-www-form-urlencoded',
}
const response = await fetch(imgix_url, { headers, method })
const body = await response.text()
console.log(body)
}
init()
I can access data.colors if I request this image from the rendering API with the palette=json parameter, so I know the property theoretically exists.
Request to https://xxxxxxx.imgix.net/test/roses.jpeg?palette=json:
{
"colors":[
{
"red":0.960784,
"hex":"#f5ece9",
"blue":0.913725,
"green":0.92549
},
{
"red":0.843137,
"hex":"#d7cb99",
"blue":0.6,
"green":0.796078
},
{
"red":0.768627,
"hex":"#c44535",
"blue":0.207843,
"green":0.270588
},
{
"red":0.670588,
"hex":"#aba544",
"blue":0.266667,
"green":0.647059
},
{
"red":0.454902,
"hex":"#746a4f",
"blue":0.309804,
"green":0.415686
},
{
"red":0.227451,
"hex":"#3a452f",
"blue":0.184314,
"green":0.270588
}
],
"average_luminance":0.387471,
"dominant_colors":{
"vibrant":{
"red":0.698039,
"hex":"#b2524d",
"blue":0.301961,
"green":0.321569
},
"muted_light":{
"red":0.823529,
"hex":"#d2b3aa",
"blue":0.666667,
"green":0.701961
},
"muted":{
"red":0.698039,
"hex":"#b2524d",
"blue":0.301961,
"green":0.321569
},
"vibrant_dark":{
"red":0.368627,
"hex":"#5e220c",
"blue":0.0470588,
"green":0.133333
},
"vibrant_light":{
"red":0.898039,
"hex":"#e5c699",
"blue":0.6,
"green":0.776471
},
"muted_dark":{
"red":0.305882,
"hex":"#4e3529",
"blue":0.160784,
"green":0.207843
}
}
}
I've tried adding a fields parameter, like this:
https://api.imgix.com/api/v1/assets/xxxxxxxxxxxxxx/test/roses.jpeg?fields[assets]=name,origin_path,colors,media_width,media_height
I get the specified properties, but they're still null.
Could anyone help me understand why these properties are coming back null?
I would like to write a prebuild script to cache the image metadata so I can set image dimensions and colorful placeholder blocks.
Thanks
I would encourage you to write into our support team (support#imgix.com) with this issue. The reason these fields return null is likely tied to your account/Source settings, which they can help you navigate. Hope that helps.
I try to type a Promise.
Funcrion's code:
const getActivityLists = async () => {
try {
//let res: Promise<Item[]>
let res: Promise<any>
if (currentPlanValue !== null) {
res = await getPlanActivityList(currentPlanValue.id)
} else {
res = await getActivitiesLists()
}
console.log(res)
createCodesList(res.data)
} catch (error) {
console.log(error)
}
}
The problem is in the 'res.data'.
The network output looks like array of objects that I need.
But if I output 'res' to console, I have this:
{
"data": [
{
"id": "f62b5c25-0d98-4b49-9706-8516875e5527",
"name": "Стажировка 2",
"description": "Как проходить стажировки",
"archive": false,
"activites": [
{
"directionId": "edf8c771-3b01-49c8-84a0-6cf4ed900370",
"activeId": "62b4c56b-3863-4373-8255-3cca6e70d478",
"order": 1,
"name": "DKO"
},
{
"directionId": "4765d688-bc40-4c4f-b039-2dc4b16d3b7c",
"activeId": "cb11db28-d7eb-413a-9348-f253a113c137",
"order": 2,
"name": "STAZH"
},
{
"directionId": "cd5bb29d-c17d-47cb-9a05-ae121c7958fc",
"activeId": "fa547f06-b00a-49fa-b647-0186b8cd3931",
"order": 3,
"name": "REGION"
}
],
"createdAt": "2022-10-28T11:04:28.924Z",
"updatedAt": "2022-10-28T11:04:28.947Z",
"activeId": "27718a9e-706d-4e23-940b-dbd10da3c5b8",
"userId": null,
"historyId": null
}
],
"status": 200,
"statusText": "OK",
"headers": {
"content-length": "4584",
"content-type": "application/json; charset=utf-8"
},
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"env": {
"FormData": null
},
"headers": {
"Accept": "application/json, text/plain, */*"
},
"method": "get",
"url": "http://localhost:3000/activitesList/list"
},
"request": {} }
My array is inside 'data', so I have to pass res.data into function 'createCodesList'.
When I try to type my 'res', I get error:
Property 'data' does not exist on type 'Promise'
How to fix it?
I don't have any idea why Promise doesn't work.
'any' means that inside promise can be anything, doesn't it?
But of course in future I want to type 'res' by my oun type Item[]. It also don't work now.
Type of your response is actual response not a promise as you already awaiting the result so
let res: Promise<any>
should be changed to
let res: any
Or as T.J. Crowder in the comment change it to actual response type
let res:{data:any} //any should be replace with actual model and other properties should be added alongwith data
I saw a few questions like mine but couldn't find any solutions that worked so I thought I'd ask.
I'm trying to pull all my data from my database so I can select parts of it in my app. I had my database working fine but when I tried to pull the pictures it failed and keeps giving me this error and also does not seem to receive the data from the database:
app.model.users.find((err,result)=>{
^
TypeError: Cannot read property 'find' of undefined
Here is my code:-
server.js:-
'use strict';
const loopback = require('loopback');
const boot = require('loopback-boot');
const app = module.exports = loopback();
app.start = function() {
// start the web server
return app.listen(function() {
app.emit('started');
const baseUrl = app.get('url').replace(/\/$/, '');
console.log('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
const explorerPath = app.get('loopback-component-explorer').mountPath;
console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
};
// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function(err) {
if (err) throw err;
// start the server if `$ node server.js`
if (require.main === module)
app.start();
});
console.log(Object.keys(app.models));
app.model.users.find((err,result)=>{
if(result.length ===0){
const user={
email:'jhanvi#gmail.com',
password:'jhanvi',
username: 'jhanvi',
};
app.models.user.create(user,(err,result)=>{
console.log("tried to create user ",err,result);
});
}
});
app.models.user.afterRemote('create', (ctx,user,next) =>{
console.log("new user is",user);
app.models.Profile.create({
first_name: user.username,
created_at: new Date(),
userId: user.id
},(err,result)=>{
if(!err && result){
console.log("created new profile",result);
}
else{
console.log("there is an error ",err);
}
});
next();
});
user.json:-
{
"name": "user",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"email": {
"type": "string"
},
"password": {
"type": "string"
}
},
"validations": [],
"relations": {
"Profile": {
"type": "hasMany",
"model": "Profile",
"foreignKey": ""
},
"accessTokens":{
"type":"hasMany",
"model":"CustomAccessToken",
"foreignKey":"userId"
}
},
"acls": [],
"methods": {}
}
Profile.json :-
{
"name": "Profile",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"created_at": {
"type": "date"
},
"age": {
"type": "number"
},
"history": {
"type": [
"object"
]
}
},
"validations": [],
"relations": {
"user": {
"type": "belongsTo",
"model": "user",
"foreignKey": "userId"
}
},
"acls": [],
"methods": {}
}
In your model you refer to user.
app.model.users.find((err,result)
should then surely be
app.model.user.find((err,result)
(i see you seem to be using both versions...)
I have a Pact file that looks like following:
{
"consumer": {
"name": "UI"
},
"provider": {
"name": "GraphQL API"
},
"interactions": [
{
"description": "Delete item request",
"providerState": "Atleast one item exists",
"request": {
"method": "POST",
"path": "/",
"headers": {
"content-type": "application/json"
},
"body": {
"operationName": null,
"query": "mutation ($itemId: ID!) { \n removeItem(id: $itemId) { \n item { \n id \n __typename \n } \n __typename \n }\n }",
"variables": {
"itemId": "item-c9b1f276-3748-4be3-915d-ec01ccbc2197"
}
},
"matchingRules": {
"$.body.query": {
"match": "regex",
"regex": "mutation\\s*\\(\\$itemId:\\s*ID!\\)\\s*\\{\\s*removeItem\\(id:\\s*\\$itemId\\)\\s*\\{\\s*plan\\s*\\{\\s*id\\s*__typename\\s*\\}\\s*__typename\\s*\\}\\s*\\}"
},
"$.body.variables.itemId": {
"match": "type"
}
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"data": {
"removeItem": {
"item": {
"id": "item-c9b1f276-3748-4be3-915d-ec01ccbc2197",
"__typename": "Item"
},
"__typename": "ItemPayload"
}
}
},
"matchingRules": {
"$.body.data.removeItem.item.id": {
"match": "type"
}
}
}
}
],
"metadata": {
"pactSpecification": {
"version": "2.0.0"
}
}
}
Before the Pact Verification, I want to provide a Valid itemId value which is a GraphQL variable.
In above JSON, its located interactions > request > body > variables > itemId
One Option I tried was Using the requestFilters option (Pact-JS-modify-requests-prior-to-verification-request-filters),
However, I am not able to understand how GraphQL variable can be modified?
Or If there is any other Verification option that can be of use?
The requestFilter capability uses raw Express JS middleware and makes no assumption about the incoming request payload content type. Thus, you will need to parse the body however makes sense for your request. For example, to extract a JSON payload you could do something like the following (tested on the GraphQL contract against the e2e provider in the Pact JS repository):
requestFilter: (req, _res, next) => {
if (req.path.match("/graphql")) {
// Body is NOT automatically converted to JSON or any specific type
// you need to extract the contents and parse
let chunks = []
req.on("data", function(chunk) {
chunks.push(chunk)
})
req.on("end", function() {
// Request upload complete, convert to a string and parse into JSON
req.body = JSON.parse(Buffer.concat(chunks).toString())
// req.body is now JSON, manipulate as needed
console.log("Body as JSON:", req.body)
next()
})
} else {
next()
}
}
I am trying to query in mongo db from loopback model. But i am not getting any result from monogdb
This is how my document looks like in mongodb
{"_id":"5b9f8bc51fbd7f248cabe742",
"agentType":"Online-Shopping",
"projectId":"modroid-server",
"labels":["category","price"],
"phrases":["Look for _^ct_ in _^p_ ",
"I need _^ct_ in _^p_",
"can you search for _^ct_ in _^p_"]
}
here is my datasource file
{
"db": {
"name": "db",
"connector": "memory"
},
"modroid-server": {
"host": "localhost",
"port": 27017,
"url": "",
"database": "modroid-server",
"password": "",
"name": "modroid-server",
"user": "",
"connector": "mongodb"
}
}
and here is model-config file
{
"_meta": {
"sources": [
"loopback/common/models",
"loopback/server/models",
"../common/models",
"./models"
],
"mixins": [
"loopback/common/mixins",
"loopback/server/mixins",
"../common/mixins",
"./mixins"
]
},
"User": {
"dataSource": "db"
},
"AccessToken": {
"dataSource": "db",
"public": false
},
"ACL": {
"dataSource": "db",
"public": false
},
"RoleMapping": {
"dataSource": "db",
"public": false,
"options": {
"strictObjectIDCoercion": true
}
},
"Role": {
"dataSource": "db",
"public": false
},
"agent": {
"dataSource": "modroid-server", // here is my mongodb
"public": true
}
}
and here is my code to query in mongodb
module.exports = function (Agent) {
Agent.getDataSource().connector.connect(function (err, db) {
var collection = db.collection("text-responses");
collection.find({ "where": { "labels": ["category", "price"] } }, function (err, res) { // define whichever query you need
console.log("collection find res:"+res);
console.log("collection find err:"+err);
if(err) {
cb(err);
return;
}
res.toArray(function (err, realRes) { // this part is crucial
// otherwise if you try to print res you will get a dump of the db object
if(err) {
cb(err);
return;
}
console.log("documnet result:"+realRes);
console.log("document err:"+err);
})
})
}
);
}
and when i hit that rest api. I get this output
collection find res:[object Object]
collection find err:null
documnet result:
document err:null
please help me where i am doing thing wrong. I am stuck in that from couples of days.
Edited
when i just print res it gives me huge data which starts as
Cursor {
pool: null,
server: null,
disconnectHandler:
Store {
s: { storedOps: [], storeOptions: [Object], topology: [Object] },
length: [Getter] },
bson: BSON {},
ns: 'modroid-server.text-responses',
cmd:
{ find: 'modroid-server.text-responses',
limit: 0,
skip: 0,
query: { where: [Object] },
slaveOk: true,
readPreference: ReadPreference { mode: 'primary', tags: undefined } },
Look like text-responses is Not a model.
Try with Direct Model Agent.
module.exports = function (Model) {
Model.getDataSource().connector.connect(function (err, db) {
Model.find({ "where": { "labels": ["category", "price"] } }, function (err, res) { // define whichever query you need
console.log("collection find res:"+res);
console.log("collection find err:"+err);
})
});
}
Or
By collection
module.exports = function (Model) {
Model.getDataSource().connector.connect(function (err, db) {
var collection = db.collection("collection-name"); //use agent
collection.find({ "where": { "labels": ["category", "price"] } }, function (err, res) { // define whichever query you need
console.log("collection find res:"+res);
console.log("collection find err:"+err);
})
}
);
}