Graphql Cannot create property 'clientMutationId' error on mutation? - graphql

this is the mutation I want to perform:
const GraphQLAddPlayerResponseMutation = mutationWithClientMutationId({
name: 'AddPlayerResponse',
inputFields: {
cdx: { type: new GraphQLNonNull(GraphQLInt) },
},
mutateAndGetPayload: ({cdx}) => {
var cdxAdded = addplayerResponse(cdx);
console.log("cdxAdded = ",cdxAdded)
return cdxAdded;
}, // what u return on mutateAndGetPayload is available on outputFields
outputFields: {
playerResponse: {
type: GraphQLInt,
resolve: ({cdxAdded}) => {
console.log("outputFields cdxAdded = ",cdxAdded)
return cdxAdded
},
},
viewer: {
type: GraphQLUser,
resolve: () => getViewer(),
},
},
});
Can't figure out what's wrong with the code, it logs on the mutateAndPayload:
mutateAndGetPayload: ({cdx}) => {
var cdxAdded = addplayerResponse(cdx);
console.log("cdxAdded = ",cdxAdded)
return cdxAdded;
},
but I think the outputFields is not evaluated since it's not logging in the console and I get this error:
{
"data": {
"addPlayerResponse": null
},
"errors": [
{
"message": "Cannot create property 'clientMutationId' on number '3'",
"locations": [
{
"line": 4,
"column": 3
}
],
"path": [
"addPlayerResponse"
]
}
]
}
Help?

Replace return cdxAdded; by return { cdxAdded }; (wild guess)

Related

How do I build a custom graphql query with support for Mongodb aggregations in Strapi?

I tried building a custom graphql query with Strapi as per below:
module.exports = {
definition: `
type flatOnts {
site_name: String
unit_no: String
firstname: String
lastName: String
description: String
isp_name: String
serial_number: String
status: Boolean
}
`,
query: `
flattenOntObj: [flatOnts]
`,
type: {},
resolver: {
Query: {
flattenOntObj: {
description: "Return a flat ont object",
resolverOf: "application::onts.onts.aggregate",
resolver: async (obj, options, ctx) => {
const res = await strapi.api.onts.services.onts.aggregate([
{
$lookup: {
from: "onts",
localField: "ont",
foreignField: "_id",
as: "ont_details",
},
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
{
$arrayElemAt: ["$ont_details", 0],
},
"$$ROOT",
],
},
},
},
]);
console.log(res);
},
},
},
},
};
However, upon running this in the Graphql playground, I am presented with the "forbidden" error.
Any ideas or pointers?
Appreciate any assistance.
Nevermind, I got it right. I missed a section on the Strapi documentation that explains it: https://strapi.io/documentation/3.0.0-beta.x/concepts/queries.html#custom-queries
In the folder: api/model/services/model.js (my case: api/onts/services/ont.js)
module.exports = {
aggregate: async (aggArray) => {
const res = await strapi.query("ont").model.aggregate(aggArray);
return res;
},
};
and then in api/onts/config/schema.graphql.js:
module.exports = {
definition: `
type flatOnts {
site_name: String
unit_no: String
firstname: String
lastName: String
description: String
isp_name: String
serial_number: String
status: Boolean
}
`,
query: `
flattenOntObj: [flatOnts]
`,
type: {},
resolver: {
Query: {
flattenOntObj: {
description: "Return a flat ont object",
// policies: ["plugins::users-permissions.isAuthenticated"],
resolverOf: "application::onts.onts.find",
resolver: async (obj, options, ctx) => {
const aggregationArray = [
{
$lookup: {
from: "onts",
localField: "ont",
foreignField: "_id",
as: "ont_details",
},
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
{
$arrayElemAt: ["$ont_details", 0],
},
"$$ROOT",
],
},
},
];
const res = await strapi.api.onts.services.onts.aggregate(
aggregationArray
);
return res;
},
},
},
},
};

schema type for an unknown object in graphql

I have the following object coming back from db:
{
"total_rows": 200,
"bookmark": "g1AAAABteJzLYWBgYMpgTmEQTM4vTc5ISXIwNDLXMwBCwxyQVCJDUv3___-zMpjc7D8wgEEiCx71eSwgJQ1A6j-GtiwA6MscCg",
"rows": [
{
"id": "51a1ff51b3b4719d05e40ac4bb0d0566",
"objects": {
"0": {
"type": "ipv4-addr",
"value": "192.168.1.10",
"resolves_to_refs": "2"
},
"1": {
"type": "network-traffic"
}
}
],
"counts": {
"created_by_ref": {
"0203a7e6-b174-4af9-812d-ab889816e868": 1,
"0250789a-14c3-4751-b4a0-c017af82b8f1": 1,
"03c63db6-2a84-4627-88be-a83208d524e6": 1,
"05cba3da-11ff-4a7a-aae9-0b1614cd5300": 1,
"fc825d33-26ea-4563-9478-2e1887b87112": 1
},
"file.hashes.MD5": {
"UNDEFINED": 200
},
"file.name": {
"UNDEFINED": 200
},
"ipv4_addr.value": {
"127.0.0.1": 200,
"192.168.1.10": 200
},
"last_observed": {
"1583503380000": 5,
"1583589780000": 9,
"1585749840000": 12
}
},
"num_of_rows": 10
}
I am trying to fit in a graphql schema to the above. I have the following which works paryially:
const graphql = require("graphql");
const { GraphQLObjectType, GraphQLString, GraphQLSchema, GraphQLInt, GraphQLList } = graphql;
const SearchResultType = new GraphQLObjectType({
name: "SearchResult",
fields: ()=>({
total_rows: { type: GraphQLInt },
bookmark: { type: GraphQLString },
//rows: { type: new GraphQLList(GraphQLInt) },
num_of_rows: { type: GraphQLInt }
})
});
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
searchResult:{
type: SearchResultType,
args: { id: { type: GraphQLString } },
resolve(parentValue: any, args: any) {
console.log(args)
return resultMock;
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery,
});
The above works for those data types which are defined. However there are some objects in the mockResult above like:
"objects": {
"0": {
"type": "ipv4-addr",
"value": "192.168.1.10",
"resolves_to_refs": "2"
},
"1": {
"type": "network-traffic"
}
or
"counts": {
"created_by_ref": {
"0203a7e6-b174-4af9-812d-ab889816e868": 1,
"0250789a-14c3-4751-b4a0-c017af82b8f1": 1,
"03c63db6-2a84-4627-88be-a83208d524e6": 1,
"05cba3da-11ff-4a7a-aae9-0b1614cd5300": 1,
"fc825d33-26ea-4563-9478-2e1887b87112": 1
So as you see these objects keys are random or at least not guessable until we receive them. Is there any way I can define a sth like this: rows: { type: new GraphQLList(any random object we do not know ) }, as a type in schema below:
const SearchResultType = new GraphQLObjectType({
name: "SearchResult",
fields: ()=>({
total_rows: { type: GraphQLInt },
bookmark: { type: GraphQLString },
rows: { type: new GraphQLList(any random object we do not know ) },
num_of_rows: { type: GraphQLInt }
})
});
You can use the GraphQL JSON Scalar (for example from this implementation). I would not recommend doing this though (in fact years ago I did a talk "GraphQL JSON Scalar considered harmful"). Instead, you might want to transform map-like objects into lists of key-value pairs.
So for example for your counts object you could do the following:
type CreatedByRef {
key: ID
count: Int
}
Object.keys(counts.created_by_ref).map(key => ({
key,
count: counts.created_by_ref[key],
}));
This will change the shape of the result but preserve all the properties of GraphQL.

How to GET variables from an Array from external API?

I'm starting with Apollo GraphQL (Using Axios), and i'm facing a problem when an external API send an ARRAY.
I can't get the variables inside the objects.
I've already tried in several ways, and can't find help anywhere.
const axios = require ('axios');
const {GraphQLObjectType, GraphQLSchema, GraphQLInt,
GraphQLList, GraphQLString } = require('graphql');
const FeedingType = new GraphQLObjectType({
name: 'Feeding',
fields: () => ({
sentry_objects : {type : new GraphQLList(SentryType)},
})
})
//Sentry Objects
const SentryType = new GraphQLObjectType({
name: 'Sentry',
fields: () => ({
designation : {type : GraphQLString},
})
})
//Root Query
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
sentry: {
type: new GraphQLList(SentryType),
resolve(parent, args){
return axios
.get('https://api.nasa.gov/neo/rest/v1/neo/sentry?is_active=true&page=0&size=50&api_key=DEMO_KEY')
.then(res => res.data);
}
},
And that's the JSON from API:
{
"links": {
"next": "https://api.nasa.gov/neo/rest/v1/neo/sentry?is_active=true&page=1&size=50&api_key=DEMO_KEY",
"self": "https://api.nasa.gov/neo/rest/v1/neo/sentry?is_active=true&page=0&size=50&api_key=DEMO_KEY"
},
"page": {
"size": 50,
"total_elements": 908,
"total_pages": 19,
"number": 0
},
"sentry_objects": [
{
"links": {
"near_earth_object_parent": "https://api.nasa.gov/neo/rest/v1/neo/3012393?api_key=DEMO_KEY",
"self": "https://api.nasa.gov/neo/rest/v1/neo/sentry/3012393?api_key=DEMO_KEY"
},
"spkId": "3012393",
"designation": "1979 XB",
"sentryId": "bJ79X00B",
"fullname": "(1979 XB)",
"year_range_min": "2056",
"year_range_max": "2113",
"potential_impacts": "2",
"impact_probability": "7.36e-07",
"v_infinity": "23.9194972826087",
"absolute_magnitude": "18.53",
"estimated_diameter": "0.662",
"palermo_scale_ave": "-2.82",
"Palermo_scale_max": "-3.12",
"torino_scale": "0",
"last_obs": "1979-Dec-15.42951",
"last_obs_jd": "2444222.92951",
"url_nasa_details": "https://cneos.jpl.nasa.gov/sentry/details.html#?des=1979+XB",
"url_orbital_elements": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=3012393;orb=1",
"is_active_sentry_object": true,
"average_lunar_distance": 14.2337865829
},
}
Trying to get that "sentry_objects" variables, testing with "designation", but i'm just getting errors like:
{
"errors": [
{
"message": "Expected Iterable, but did not find one for field RootQueryType.sentry.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"sentry"
]
}
],
"data": {
"sentry": null
}
}
Thank you for reading :)
In your RootQuery resolver you are only returning from the promise res.data object, but you should return the res.data.sentry_object object.
Something like:
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
sentry: {
type: new GraphQLList(SentryType),
resolve(parent, args) {
return axios
.get('https://api.nasa.gov/neo/rest/v1/neo/sentry?is_active=true&page=0&size=50&api_key=DEMO_KEY')
.then(res => {
// HERE: return the sentry_objects
console.log(res.data.sentry_objects)
return res.data.sentry_objects
});
}
},
}
})

ExtJS: How to hide specific data on store with filtering?

I want to hide a record on Grid that returns from server.
I've setted a filter on store and can reach that specific data but how I'll handle to hide/ignore this record?
fooStore: {
....
filters: [
function(item) {
let me = this;
let theRecord = item.data.status === MyApp.STATUS; //true
if (theRecord) {
console.log(theRecord); //True
console.log("So filter is here!!")
//How to hide/ignore/avoid to load this specific data record to load Grid??
}
}
]
},
Returned JSON;
{
"success": true,
"msg": "OK",
"count": 3,
"data": [
{
//Filter achives to this record and aim to hide this one; avoid to load this record.
"id": 102913410,
"status": "P"
},
{
"id": 98713410,
"status": "I"
},
{
"id": 563423410,
"status": "A"
}
]
}
I can't save my fiddle cause i don't have sencha forum's account so i give you my code :
Ext.application({
name : 'Fiddle',
launch : function() {
var model = Ext.create('Ext.data.Model', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'status', type: 'string'},
]
});
var store = Ext.create('Ext.data.Store', {
autoLoad: true,
model: model,
proxy: {
type: 'ajax',
url: 'data.json',
reader: {
type: 'json',
rootProperty: 'data'
}
},
filters: [function(item) {
if (item.data.status === "P") {
return true;
}
else {
return false;
}
}],
listeners: {
load: {
fn: function() {
console.log(this.getRange());
}
}
}
});
}
});
Also i create data.json like this :
{
"success": true,
"msg": "OK",
"count": 3,
"data": [{
"id": 102913410,
"status": "P"
}, {
"id": 98713410,
"status": "I"
}, {
"id": 563423410,
"status": "A"
}]
}
I thinks it's near to you'r code and after the loading of the store the filter work as you can this :
Here is sencha fiddle link : https://fiddle.sencha.com/#view/editor
If this can't work, i don't understand what the fuck doing...

How can I get graphql to output this list of object for the client?

I have a graphql server, and I am trying to implement a query that will update the client with a list of nodes.
In nodes.js I have:
export const nodes = {
"nodes": [
{id: 1, "name": 'building_1', "hasStrobe": true},
{id: 2, "name": 'building_2', "hasStrobe": false},
{id: 3, "name": 'building_3', "hasStrobe": true}
]
}
My query in schema.js is as follows:
const Query = new GraphQLObjectType({
name: 'Query',
description: 'Root query object',
fields() {
return {
message: {
type: Message,
resolve() {
return getMessage();
},
},
system: {
type: System,
resolve() {
return getSystemInfo();
},
},
nodes: {
type: Nodes,
resolve() {
//console.log(nodes.nodes)
return nodes.nodes;
}
},
// alert: {
// type: Alert,
// resolve() {
// return 'poke';
// }
// }
};
},
});
And my Nodes type is as follows:
const Nodes = new GraphQLObjectType({
name: 'Nodes',
description: 'List of zone nodes and their capabilities.',
fields() {
return {
nodes: {
type: GraphQLString,
resolve(msg) {
console.log(msg)
return msg;
}
},
}
}
});
When the query is run, it logs nodes.nodes correctly to the console:
[ { id: 1, name: 'building_1', hasStrobe: true },
{ id: 2, name: 'building_2', hasStrobe: false },
{ id: 3, name: 'building_3', hasStrobe: true } ]
While the query output is:
{
"data": {
"system": {
"uname": "4.11.5-2-ck-haswell\n",
"time": "Thu Jun 22 2017 17:39:29 GMT-0500 (CDT)"
},
"nodes": {
"nodes": "[object Object],[object Object],[object Object]"
}
}
}
I'm unsure of how to process the data array in a way that will work to output the nodes.

Resources