Why GraphQL is not detecting a new field in a JSON object - javascript

I'm new in Gatsby Development, in my website I'm using a community theme and modifying it in some things.
My problem started when I modified a JSON file called 'settings.json', where I added a field in the siteConfiguration object, the original file was this:
{"siteConfiguration": {
"logo": { "text": "chrisley"},
"navigation": {
"header": [
{ "label": "About", "url": "/#about" },
{ "label": "Blog", "url": "/blog" },
{ "label": "Features", "url": "/#features" },
{ "label": "Github", "url": "/#github" }
],
"ctaButton": {
"openNewTab": true,
"label": "Resume",
"url": "/resume.pdf"
},
"footer": [
{ "label": "Privacy", "url": "/privacy" },
{ "label": "Imprint", "url": "/imprint" }
]
},
"featureToggles": {
"useDarkModeAsDefault": false,
"useDarkModeBasedOnUsersPreference": true,
"useCookieBar": false
}
}
}
And the one where I added the field 'img' inside "logo" is the following:
{"siteConfiguration": {
"logo": { "text": "chrisley","img":"/content/images/logo-dark.png"},
"navigation": {
"header": [
{ "label": "About", "url": "/#about" },
{ "label": "Blog", "url": "/blog" },
{ "label": "Features", "url": "/#features" },
{ "label": "Github", "url": "/#github" }
],
"ctaButton": {
"openNewTab": true,
"label": "Resume",
"url": "/resume.pdf"
},
"footer": [
{ "label": "Privacy", "url": "/privacy" },
{ "label": "Imprint", "url": "/imprint" }
]
},
"featureToggles": {
"useDarkModeAsDefault": false,
"useDarkModeBasedOnUsersPreference": true,
"useCookieBar": false
}
}
}
And when I trying to get the img field in GraphQL with this Query:
query SiteConfiguration {
allSettingsJson: allContentJson {
settings: nodes {
siteConfiguration {
logo {
text
img
}
}
}
}
}
I get the next error:
{
"errors": [
{
"message": "Cannot query field \"img\" on type \"Logo\".",
"locations": [
{
"line": 7,
"column": 11
}
],
"extensions": {
"stack": [
"GraphQLError: Cannot query field \"img\" on type \"Logo\".",
" at Object.Field (/Users/chrisley/Documents/Development/Gatsby/chrisley_dev_website/node_modules/graphql/validation/rules/FieldsOnCorrectTypeRule.js:48:31)",
" at Object.enter (/Users/chrisley/Documents/Development/Gatsby/chrisley_dev_website/node_modules/graphql/language/visitor.js:323:29)",
" at Object.enter (/Users/chrisley/Documents/Development/Gatsby/chrisley_dev_website/node_modules/graphql/utilities/TypeInfo.js:370:25)",
" at visit (/Users/chrisley/Documents/Development/Gatsby/chrisley_dev_website/node_modules/graphql/language/visitor.js:243:26)",
" at validate (/Users/chrisley/Documents/Development/Gatsby/chrisley_dev_website/node_modules/graphql/validation/validate.js:69:24)",
" at graphqlMiddleware (/Users/chrisley/Documents/Development/Gatsby/chrisley_dev_website/node_modules/express-graphql/index.js:98:38)",
" at processTicksAndRejections (node:internal/process/task_queues:95:5)"
]
}
}
]
}
Hope you can help me guys, as always haha 😅

I'll be answering myself because I found the problem hahaha.
The problem was that I was missing updating the Schema of the theme, in particular of this theme was the file gastby/node/createSchemaCustomization.js
So.. after updating the file with this lines:
module.exports = ({ actions }) => {
actions.createTypes(`
...
type Logo {
text: String
img: String
}
...
`);
};
GraphQL detected my new field 'img' of the 'logo' object.

After some research I'm assuming you are using the following starter: https://github.com/konstantinmuenster/gatsby-theme-portfolio-minimal/tree/main/gatsby-theme-portfolio-minimal
Have you tried stopping your development process and cleaning Gatsby cache by:
gatsby clean
Or manually deleting the .cache folder.

Related

AWS DataExchange API fetch returning response '404: Asset not found'

I'm trying to fetch data from an AWS DataExchange provider based on their company's API specification.
I'm using the AWS Node.JS NPM modules 'aws-sdk' and '#aws-sdk/client-dataexchange'.
However, every query I've written is returning the error '404: Asset not found'.
I'm subscribed to use the API and I've verified that all my AWS credentials, policies and IAM keys give me permission to access the API.
Could someone please help me identify what's wrong with my query in relation to the API specification.
Thanks!
The response I get looks like below:
404: Asset not found
'$fault': 'client',
'$metadata': {
httpStatusCode: 404,
requestId: 'b7e6e691-xxxxxxx7657201138a4',
extendedRequestId: undefined,
cfId: 'dBQBwlCE8cXp4--xxxxxxxxxxx3j2lTfxywUezCPEA6nusJCJg==',
attempts: 1,
totalRetryDelay: 0
},
ResourceType: 'ASSET',
ResourceId: 'e055c882bde1fa3xxxxxxxxx'
}
My current request 'body' looks like below:
Body: JSON.stringify({
"description": "GraphQL query for the Ursa Space Imagery Catalog.",
"content": {
"application/graphql": {
"schema": {
"$ref": "#/components/schemas/CatalogSearchRequest"
},
"query": {
"description": "Limit the number of records in a response.",
"value":"{\n availablemetadatarecord(\n limit: 20\n content: { catalogProperties: { vendor: { eq: \"ICEYE\" } } }\n ) {\n assignedId\n }\n}\n"
}
}
},
"required": true
}),
The DataExchange provider's actual API specification looks like below:
{
"openapi": "3.0.1",
"info": {
"title": "image-services",
"description": "API Gateway for integration of Platform Services into AWS Data Exchange",
"version": "2022-03-03T20:04:18Z"
},
"servers": [
{
"url": ""
}
],
"paths": {
"/psdm/graphql": {
"post": {
"requestBody": {
"description": "GraphQL query for the Catalog in the form of:\n\n `{\n availablemetadatarecord(\n QUERYPARAMS\n ) { \n FIELDLIST\n } \n }`\n",
"content": {
"application/graphql": {
"schema": {
"$ref": "#/components/schemas/CatalogSearchRequest"
},
"examples": {
"Limit returned data": {
"description": "Limit the number of records in a response.\n\nIn your query, simply specify `limit: <int>` \n",
"value": "{\n availablemetadatarecord(\n limit: 10\n content: { catalogProperties: { vendor: { eq: \"EYE\" } } }\n ) {\n assignedId\n }\n}\n"
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "200 response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CatalogSearchResponse"
}
}
}
}
},
"security": [
{
"sigv4": []
}
]
}
}
},
"components": {
"schemas": {
"CatalogSearchRequest": {
"title": "CatalogSearchRequest",
"type": "object"
},
"CatalogSearchResponse": {
"title": "Catalog Search Response",
"required": [
"data",
"paginationInfo"
],
"type": "object",
"properties": {
"paginationInfo": {
"type": "object",
"properties": {
"recordsInPage": {
"type": "integer"
},
"nextOffset": {
"type": "integer"
}
}
},
"data": {
"type": "object",
"properties": {
"availablemetadatarecord": {
"type": "array",
"description": "Records returned by query",
"items": {
"type": "object"
}
}
}
}
}
}
},
"securitySchemes": {
"sigv4": {
"type": "apiKey",
"name": "Authorization",
"in": "header",
"x-amazon-apigateway-authtype": "awsSigv4"
}
}
}
}

Enable root URL for Asymmetrik FHIR server to save Bundle transactions?

My team is building a health app and thus using Asymmetrik FHIR API Server. We need to save a bundle consisting of Condition, Observation and Procedure. The bundle should create each individual object in their respective tables. But when we are using postman to hit the base URL with a very simple bundle object it is giving Invalid URL. Each service is individually working fine and able to create respective objects. How can we enable the root URL of this FHIR server?
POST URL: http://localhost:3000/4_0_0/
POST Object:
{
"resourceType": "Bundle",
"id": "f001",
"type": "transaction",
"entry": [
{
"resource": {
"resourceType": "Observation",
"status": "registered"
},
"request": {
"method": "POST",
"url": "Observation"
}
},
{
"resource": {
"resourceType": "Condition",
"code": {
"coding": {
"system": "http://hl7.org/fhir/ValueSet/condition-code",
"code": "",
"display": ""
}
}
},
"request": {
"method": "POST",
"url": "Condition"
}
}
]
}
ERROR:
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "not-found",
"details": {
"text": "Invalid url: /4_0_0/"
}
}
]
}

Exact search with ElasticSearch 7.x

I am trying to find an exact search for an url with ElasticSearch ("#elastic/elasticsearch": "^7.5.0").
I have configured my mapping like so:
const schema = {
userId: {
type: "keyword"
},
url: {
type: "keyword",
index: false,
analyzer: 'keyword'
},
pageTitle: {
type: 'text',
},
pageText: {
type: 'text',
}
};
await client.indices.putMapping({
index,
type,
include_type_name: true,
body: {
properties: schema
}
})
I have tried different queries, and they looks like this:
body: {
query: {
bool: {
must: {
match: {
query: 'test stack',
analyzer: 'keyword',
}
}
}
}
}
Or second attempt:
body: {
query: {
constant_score: {
filter: {
bool: {
must: {
term: {
url: 'test stack'
}
}
}
}
},
}
}
None of them work. I want to get only the results where the exact string 'test/stack' is found. Any help would be highly appreciated.
Example of data I'm trying to add:
[
{"url": "test stack",
"userId": "anotherTest",
"pageTitle": "not important",
"pageText": "not important",
"log": [1, 3, 7]
},
{"url": "test stack",
"userId": "anotherTest",
"pageTitle": "not important",
"pageText": "not important",
"log": [1, 3, 7]
},
{"url": "test stack",
"userId": "anotherTest",
"pageTitle": "not important",
"pageText": "not important",
"log": [1, 3, 7]
}
]
Thanks.
I managed to make this work. Steps are:
1. Delete the index.
2. Delete the custom mapping function.
3. Create the index (with client.indices.create)
4. Index the first item (with client.index).
5. At this point, you can check in postman the dynamic mappings created by ElasticSearch (only visible after 1st item is indexed, by what I could tell). You can make a get request at http://localhost:9200/history/_mappings, and the response should look something like this:
{
"history": {
"mappings": {
"properties": {
"fullTitle": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"log": {
"properties": {
"startTime": {
"type": "long"
},
"timeSpent": {
"type": "long"
}
}
},
"protocol": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"text": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"totalTimeSpent": {
"type": "long"
},
"totalVisits": {
"type": "long"
},
"url": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"userId": {
"type": "long"
}
}
}
}
}
As you can see, any field indexed as text has attached another field, called keyword, which can be used for exact matches.
6. The query to get the exact matches looks like this:
const result = await esClient.search({
index: 'history',
body: {
query: {
term: {
'url.keyword': {
value: toInsert.url
}
}
}
}
})
At this point you should receive results only in case of exact match for the field "url" in my case. Hope this helps somebody else. Thanks #ibexit for trying to help me.
I see two problems:
The mapping defined for the url field says
url: {
type: "keyword",
index: false,
analyzer: 'keyword'
},
If you define index: false, the field will not be searchable at all. Using the following mapping should work properly:
url: {
type: "keyword"
}
See https://www.elastic.co/guide/en/elasticsearch/reference/current/keyword.html for more detailed information
The keyword mapped fields will not match using the match query which is designed to query text fields. Please use the term query instead for keyword fields. Please notice the example below using the Elasticseaech Query API:
GET /_search
{
"query": {
"term": {
"url": { <<= the field to search
"value": "test stack" <<= the searched value
}
}
}
}
Here is the according documentation: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html
BTW: keep in mind that you need to reindex the data after a mapping change

Get back the whole JSON request from google action with Node js client library

I am using actions-on-goolge library for nodejs https://www.npmjs.com/package/actions-on-google
How would I able to get the whole JSON response, or use id string inside my intent function? I have tried to print out the input, it only gives the query part of the JSON. Tried to look up their documentation, it does not seem to explain how I could get back the whole JSON file.
https://developers.google.com/actions/reference/nodejs/lib-v1-migration
I am beginner of javascript.
The JSON request from simulator:
{
"user": {
"userId": "ABwppHEAPgcgb2yFUFURYFEJGg4VdAVcL9UKO9cS7a7rVfasdasdt67LzgrmMseTvb5mmJjbjj7UV",
"locale": "en-US",
"lastSeen": "2018-05-11T23:14:42Z",
"userStorage": "{\"data\":{}}"
},
"conversation": {
"conversationId": "1526080586367",
"type": "NEW"
},
"inputs": [
{
"intent": "com.example.device.OFF",
"rawInputs": [
{
"inputType": "KEYBOARD",
"query": "Talk to MyDevice to turn off"
}
],
"arguments": [
{
"name": "trigger_query",
"rawText": "turn off",
"textValue": "turn off"
}
]
}
],
"surface": {
"capabilities": [
{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name": "actions.capability.WEB_BROWSER"
},
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
}
]
},
"isInSandbox": true,
"availableSurfaces": [
{
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
}
]
}
]
}
My Node JS script base on the example:
const express = require('express')
const bodyParser = require('body-parser')
const {
actionssdk,
Image,
} = require('actions-on-google')
app.intent('actions.intent.TEXT', (conv, input) => {
if (input === 'bye' || input === 'goodbye') {
return conv.close('See you later!')
}
conv.ask(`I didn't understand. Can you tell me something else?`)
})
app.intent('com.example.MyDevice.TEST', (conv, input) => {
console.log(input);
console.log(conv.action);
console.log(conv.intent);
conv.close('Test Done');
});
express().use(bodyParser.json(), app).listen(3000)
You should be able to get the entire JSON request through conv.body.

Why are relations not being added to my loopback.io objects in the models?

I am quite new to Loopback and NodeJS, so please tell me if there is a "Node way" of doing something that I am missing. I decided to write a basic application to try and learn more.
I have two models, 'UserInformation' and 'ClothingArticle'. I have created a 'hasMany' relation from UserInformation to ClothingArticle.
As a basic test, I wanted to add a remote method to UserInformation to get recommendations for ClothingArticles. However, I cannot seem to get access to anything related to ClothingArticles. I added code into the common/models/user-information.js file to try and retrieve information about the relation, but am not sure if this is even the right spot to be putting it.
My code is below, could you help?
common/models/user-information.js:
module.exports = function(UserInformation) {
get_methods = function(obj) {
var result = [];
for(var id in obj) {
try {
if(typeof(obj[id]) == "function") {
result.push(id + " (function): "); //+ obj[id].toString());
}
else
result.push(id + ": "); // + obj[id].toString());
}
catch (err) {
result.push(id + ": inaccessible");
}
}
return result;
}
// This doesn't anything about my new relations?
console.log(get_methods(UserInformation.prototype));
UserInformation.recommendations = function(source, callback) {
var response = "I don't have any recommendations.";
var test_function = UserInformation.findById(3, function(err, instances) {
if(err) return console.log("Errors: " + err);
console.log("Instances: " + String(instances));
// Nothing here either about the relations.
console.log(get_methods(UserInformation));
console.log(UserInformation.app);
/*
instances.clothingArticles.create({
id:92,
colors:['red','blue']
});
*/
console.log("Created a new clothing article.");
});
console.log (response);
callback(null, response);
}
UserInformation.remoteMethod(
'recommendations',
{
accepts: [
{arg: 'source', type: 'string'} // Used to mark the source (closet, generic, etc)
],
http: {path: '/recommendations', verb: 'get'},
returns: {arg: 'recommendations', type: 'string'}
}
);
};
common/models/user-information.json:
{
"name": "UserInformation",
"base": "PersistedModel",
"strict": false,
"idInjection": false,
"properties": {
"birthday": {
"type": "date"
},
"id": {
"type": "number",
"id": true,
"required": true
},
"eye_color": {
"type": "string"
},
"hair_color": {
"type": "string"
},
"weight": {
"type": "string",
"comments": "pounds"
},
"height": {
"type": "number",
"comments": "inches"
}
},
"validations": [],
"relations": {
"clothingArticles": {
"type": "hasMany",
"model": "ClothingArticle",
"foreignKey": "owner_id"
}
},
"acls": [],
"methods": []
}
common/models/clothing-article.json:
{
"name": "ClothingArticle",
"base": "PersistedModel",
"strict": false,
"idInjection": false,
"properties": {
"id": {
"type": "number",
"id": true,
"required": true
},
"colors": {
"type": [
"Color"
],
"required": true
},
"owner_id": {
"type": "number"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": []
}
I suggest starting with our getting started example and working your way through through the tutorial series here: https://github.com/strongloop/loopback-example
The questions you ask are answered throughout the examples (ie. model relations). To answer your question, if you defined a relation properly, you should be able to access the relation via dot.
...
UserInformation.ClothingArticle...
...
See http://docs.strongloop.com/display/LB/HasMany+relations for more information.

Categories