GraphQL mutation variables with objects - ecmascript-6

I'm trying to do something like this:
export const CREATE_BUSINESS = gql`
mutation createBusinessMutation(
$name: String!
$website: String!
$streetAddress: String!
$city: String!
$countryCode: String!
$postCode: String!
) {
business(
input: {
name: $name
number: $number
website: $website
address: {
streetAddress: $streetAddress
city: $city
countryCode: $countryCode
postCode: $postCode
}
}
) {
id
name
}
}
`;
and I'm having this error:
1: {message: "Variable "$streetAddress" of required type "[String]!" was not provided.",…}
2: {message: "Variable "$city" of required type "[String]!" was not provided.",…}
3: {message: "Variable "$countryCode" of required type "[String]!" was not provided.",…}
4: {message: "Variable "$postCode" of required type "[String]!" was not provided.",…}
I'm only having this issue when I nest as an object otherwise it works.
Any help?

Related

how to call struct into my post Request and how to bind the data

struct LogIn: Codable {
let data: DataClass
let success: Bool
let successCode, httpstatusCode: Int
let developerMessage, userMessage, header: String
}
struct DataClass: Codable {
let userID: Int
let name, email, phone, dob: String
let status: Bool
let password: String
enum CodingKeys: String, CodingKey {
case userID = "UserID"
case name = "Name"
case email = "Email"
case phone = "Phone"
case dob = "DOB"
case status = "Status"
case password = "Password"
}
}
this is my json struct and my link is there .. and i wonder how to bind the data in my login page
i have added my login base Code here for reference.
VStack{
VStack(alignment: .center, spacing: 20){
TextField("Email", text: $email)
.keyboardType(.emailAddress)
.frame(width: 320, height: 40, alignment: .center)
.padding()
SecureField("Password", text: $password)
.padding()
Button(action: {
self.manager.PostAPI(email: self.email, password: self.password)
shownext = true
}){
Text("Sign In")
}
}
}
.fullScreenCover(isPresented: $showsignup) {
Sign_Up()
}
.fullScreenCover(isPresented: $showFP) {
ForgetPssword()
}
.fullScreenCover(isPresented: $shownext, content: {
Dummy(selection: self.$shownext)
})
need to help for bind the value also. i just wonder how to do bind the login page. am a newbie of the Swiftui and IOS also. help me out of this.

I'm facing problem decoding a HTML script as string value from JSON, every other value is being converted just fine

I'm working with a JSON response where the value of a key contains HTML as string, it's not very large still it's not decoding. Here is my JSON Response
{
"authentication": {
"3ds1": {
"veResEnrolled": "Y"
},
"payerInteraction": "REQUIRED",
"redirect": {
"domainName": "www.abc.com"
},
"redirectHtml": "<div id=\"abcabcabc\" xmlns=\"xyzxyz"> <iframe id=\"redirectTo3ds1Frame\" name=\"redirectTo3ds1Frame\" height=\"100%\" width=\"100%\" > </iframe> <form id =\"xyz123\" method=\"POST\" action=\"https://domain.name" target=\"redirectTo3ds1Frame\"> <input type=\"hidden\" name=\"PaReq\" value=\"Some text" /> <input type=\"hidden\" name=\"TermUrl\" value=\"https:/url" /> <input type=\"hidden\" name=\"MD\" value=\"\" /> </form> <script id=\"authenticate-payer-script\"> var e=document.getElementById(\"someID\"); if (e) { e.submit(); if (e.parentNode !== null) { e.parentNode.removeChild(e); } } </script> </div>",
"version": "3DS1"
},
"correlationId": "testxyz123450",
"device": {
"browser": "MOZILLA",
"ipAddress": "127.0.0.1"
},
"merchant": "ABC123",
"response": {
"gatewayCode": "PENDING",
"gatewayRecommendation": "PROCEED"
},
"result": "PENDING",
"timeOfLastUpdate": "2021-07-25T06:11:09.511Z",
"timeOfRecord": "2021-07-25T06:10:51.208Z",
}
This is my model by I'm using
// MODEL CODE
import Foundation
// MARK: - AuthPayer
class AuthPayer: Codable {
var timeOfLastUpdate, timeOfRecord: String?
var device: Device?
var merchant: String?
var authentication: Authentication?
var result: String?
var correlationID: String?
var response: Response?
enum CodingKeys: String, CodingKey {
case timeOfLastUpdate, timeOfRecord, device, merchant, authentication, result, transaction
case correlationID
case response
}
init( timeOfLastUpdate: String?, timeOfRecord: String?, device: Device?, merchant: String?, authentication: Authentication?, result: String?, transaction: Transaction?, correlationID: String?, response: Response?) {
self.timeOfLastUpdate = timeOfLastUpdate
self.timeOfRecord = timeOfRecord
self.device = device
self.merchant = merchant
self.authentication = authentication
self.result = result
self.correlationID = correlationID
self.response = response
}
}
// MARK: - Authentication
class Authentication: Codable {
var redirect: Redirect?
var redirectHTML: String?
var the3Ds1: The3Ds1?
var payerInteraction, version: String?
enum CodingKeys: String, CodingKey {
case redirect
case redirectHTML
case the3Ds1
case payerInteraction, version
}
init(redirect: Redirect?, redirectHTML: String?, the3Ds1: The3Ds1?, payerInteraction: String?, version: String?) {
self.redirect = redirect
self.redirectHTML = redirectHTML ?? """
"""
self.the3Ds1 = the3Ds1
self.payerInteraction = payerInteraction
self.version = version
}
}
// MARK: - Redirect
class Redirect: Codable {
var domainName: String?
init(domainName: String?) {
self.domainName = domainName
}
}
// MARK: - The3Ds1
class The3Ds1: Codable {
var veResEnrolled: String?
init(veResEnrolled: String?) {
self.veResEnrolled = veResEnrolled
}
}
// MARK: - Device
class Device: Codable {
var browser, ipAddress: String?
init(browser: String?, ipAddress: String?) {
self.browser = browser
self.ipAddress = ipAddress
}
}
// MARK: - ValueTransfer
class ValueTransfer: Codable {
var accountType: String?
init(accountType: String?) {
self.accountType = accountType
}
}
// MARK: - Response
class Response: Codable {
var gatewayRecommendation, gatewayCode: String?
init(gatewayRecommendation: String?, gatewayCode: String?) {
self.gatewayRecommendation = gatewayRecommendation
self.gatewayCode = gatewayCode
}
}
// MARK: - Provided
class Provided: Codable {
var card: Card?
init(card: Card?) {
self.card = card
}
}
// MARK: - Acquirer
class Acquirer: Codable {
var merchantID: String?
enum CodingKeys: String, CodingKey {
case merchantID
}
init(merchantID: String?) {
self.merchantID = merchantID
}
}
by using this method I'm decoding
let authPayer = try? decoder.decode(AuthPayer.self, from: theJSONData)
from authPayer i can access authPayer?.authentication?.redirect?.domainName
and other all properties but authPayer?.authentication?.redirectHTML does not getting any value. i Have printed out the response in log and it does have all the values including "redirectHtml"
I tried Multiline String Literals to store the value not but, I can’t figure out where it's having the issue only for "redirectHtml", i need the vqlue of redirectHtml from authPayer. Please help me out

how can I fix sql type error with diesel and juniper for mysql in graphQL mutation?

I confronted the error logs below when I try to create mutation with graphGL and mysql via diesel.
currently the type of enum is just diesel's type but I want to make that with graphQl's type.
I implemented Customer Structure for graphQL like below.
is it not enough ? and do you have any idea to fix that ?
Thanks
Error log
error[E0277]: the trait bound `graphql::Customer: diesel::Queryable<(diesel::sql_types::Unsigned<diesel::sql_types::BigInt>, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Timestamp, diesel::sql_types::Timestamp), _>` is not satisfied
--> src/graphql.rs:60:14
|
60 | .first::<crate::graphql::Customer>(&executor.context().db_con)
| ^^^^^ the trait `diesel::Queryable<(diesel::sql_types::Unsigned<diesel::sql_types::BigInt>, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Timestamp, diesel::sql_types::Timestamp), _>` is not implemented for `graphql::Customer`
|
= note: required because of the requirements on the impl of `diesel::query_dsl::LoadQuery<_, graphql::Customer>` for `diesel::query_builder::SelectStatement<schema::customers::table, diesel::query_builder::select_clause::DefaultSelectClause, diesel::query_builder::distinct_clause::NoDistinctClause, diesel::query_builder::where_clause::NoWhereClause, diesel::query_builder::order_clause::NoOrderClause, diesel::query_builder::limit_clause::LimitClause<diesel::expression::bound::Bound<diesel::sql_types::BigInt, i64>>>`
src/graphql.rs
use std::convert::From;
use std::sync::Arc;
use chrono::NaiveDateTime;
use actix_web::{web, Error, HttpResponse};
use futures01::future::Future;
use juniper::http::playground::playground_source;
use juniper::{http::GraphQLRequest, Executor, FieldResult, FieldError,ID};
use juniper_from_schema::graphql_schema_from_file;
use diesel::prelude::*;
use itertools::Itertools;
use crate::schema::customers;
use crate::{DbCon, DbPool};
graphql_schema_from_file!("src/schema.graphql");
pub struct Context {
db_con: DbCon,
}
impl juniper::Context for Context {}
pub struct Query;
pub struct Mutation;
impl QueryFields for Query {
fn field_customers(
&self,
executor: &Executor<'_, Context>,
_trail: &QueryTrail<'_, Customer, Walked>,
) -> FieldResult<Vec<Customer>> {
//type FieldResult<T> = Result<T, String>;
customers::table
.load::<crate::models::Customer>(&executor.context().db_con)
.and_then(|customers| Ok(customers.into_iter().map_into().collect()))
.map_err(Into::into)
}
}
impl MutationFields for Mutation {
fn field_create_customer(
&self,
executor: &Executor<'_, Context>,
_trail: &QueryTrail<'_, Customer, Walked>,
name: String,
email: String,
) -> FieldResult<Customer> {
//type FieldResult<T> = Result<T, String>;
let new_customer = crate::models::NewCustomer { name: name, email: email};
diesel::insert_into(customers::table)
.values(&new_customer)
.execute(&executor.context().db_con);
customers::table
.first::<crate::graphql::Customer>(&executor.context().db_con)
.map_err(Into::into)
}
}
pub struct Customer {
id: u64,
name: String,
email: String,
created_at: NaiveDateTime,
updated_at: NaiveDateTime,
}
impl CustomerFields for Customer {
fn field_id(&self, _: &Executor<'_, Context>) -> FieldResult<juniper::ID> {
Ok(juniper::ID::new(self.id.to_string()))
}
fn field_name(&self, _: &Executor<'_, Context>) -> FieldResult<&String> {
Ok(&self.name)
}
fn field_email(&self, _: &Executor<'_, Context>) -> FieldResult<&String> {
Ok(&self.email)
}
}
impl From<crate::models::Customer> for Customer {
fn from(customer: crate::models::Customer) -> Self {
Self {
id: customer.id,
name: customer.name,
email: customer.email,
created_at: customer.created_at,
updated_at: customer.updated_at,
}
}
}
fn playground() -> HttpResponse {
let html = playground_source("");
HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(html)
}
fn graphql(
schema: web::Data<Arc<Schema>>,
data: web::Json<GraphQLRequest>,
db_pool: web::Data<DbPool>,
) -> impl Future<Item = HttpResponse, Error = Error> {
let ctx = Context {
db_con: db_pool.get().unwrap(),
};
web::block(move || {
let res = data.execute(&schema, &ctx);
Ok::<_, serde_json::error::Error>(serde_json::to_string(&res)?)
})
.map_err(Error::from)
.and_then(|customer| {
Ok(HttpResponse::Ok()
.content_type("application/json")
.body(customer))
})
}
pub fn register(config: &mut web::ServiceConfig) {
let schema = std::sync::Arc::new(Schema::new(Query, Mutation));
config
.data(schema)
.route("/", web::post().to_async(graphql))
.route("/", web::get().to(playground));
}
src/models.rs
#[derive(Queryable, Identifiable, AsChangeset, Clone, PartialEq, Debug)]
pub struct Customer {
pub id: u64,
pub name: String,
pub email: String,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
}
use super::schema::customers;
#[derive(Queryable,Insertable, AsChangeset)]
#[table_name="customers"]
pub struct NewCustomer {
pub name: String,
pub email: String,
}
Dependencies
[dependencies]
diesel = { version = "1.4.5", features = ["mysql", "r2d2", "chrono"] }
dotenv = "~0.15"
serde = "~1.0"
serde_derive = "~1.0"
serde_json = "~1.0"
chrono = "~0.4"
rand = "0.7.3"
actix-web = "1.0.9"
actix-cors = "0.1.0"
juniper = "0.14.1"
juniper-from-schema = "0.5.1"
juniper-eager-loading = "0.5.0"
r2d2_mysql = "*"
r2d2-diesel = "0.16.0"
mysql = "*"
r2d2 = "*"
futures01 = "0.1.29"
itertools = "0.8.2"
src/schema.graphql
schema {
query: Query
mutation: Mutation
}
type Query {
customers: [Customer!]! #juniper(ownership: "owned")
}
type Mutation {
createCustomer(
name: String!,
email: String!,
): Customer! #juniper(ownership: "owned")
}
type Customer {
id: ID! #juniper(ownership: "owned")
name: String!
email: String!
}
src/schema.rs
table! {
customers (id) {
id -> Unsigned<Bigint>,
name -> Varchar,
email -> Varchar,
created_at -> Timestamp,
updated_at -> Timestamp,
}
}
As the error message mentions you need to implement Queryable for your struct Customer in src/graphql.rs (That struct in just below where the error message points to). The easiest way to do that is to just add a #[derive(Queryable)] to this struct.

How to make structs for this JSON with Decodable protocol?

I've got this JSON:
{
"$type": "DTOMapper.DTOResponseList`1[[Telemed.Dto.DTOTip, Telemed.Dto]], DTOMapper",
"ResponseList": {
"$type": "System.Collections.Generic.List`1[[Telemed.Dto.DTOTip, Telemed.Dto]], mscorlib",
"$values": [
{
"$type": "Telemed.Dto.DTOTip, Telemed.Dto",
"Title": "NO TE JUNTES CON LUQUITAS",
"Text": "Porque si tenes un amigo lucas y otro amigo lucas, tenés dos lucas. Pero no te sirven para pagar nada",
"GroupName": "TGC.Tips1",
"ConfigurationPath": "TelemedGlobalConfig>Tips>Tips[0]"
},
{
"$type": "Telemed.Dto.DTOTip, Telemed.Dto",
"Title": "no te emborraches en las fiestas",
"Text": "Terminarás pateando globos",
"GroupName": "TGC.Tips2",
"ConfigurationPath": "TelemedGlobalConfig>Tips>Tips[1]"
}
]
},
"StatusCode": 200,
"ErrorId": 0
}
And I'm trying to get access to Title and Text from the array $values.
Here are my current structs but Root gives me errors.
struct Root : Decodable { // <<< Type 'Root' does not conform to protocol 'Decodable'
private enum CodingKeys : String, CodingKey { case responseList = "ResponseList" }
let responseList : ResponseList // <<< Use of undeclared type 'ResponseList'
}
struct Values : Decodable {
private enum CodingKeys : String, CodingKey {
case title = "Title"
case text = "Text"
}
let title : String
let text : String
}
What is the correct way to make this? Also, do I have to make a struct and let for everything? Even for things I won't use, like $type, GroupName?
What is the correct way to make this?
do {
let res = try JSONDecoder().decode(Root.self, from: data)
}
catch {
print(error)
}
struct Root: Codable {
let type: String
let responseList: ResponseList
let statusCode, errorID: Int
enum CodingKeys: String, CodingKey {
case type = "$type"
case responseList = "ResponseList"
case statusCode = "StatusCode"
case errorID = "ErrorId"
}
}
// MARK: - ResponseList
struct ResponseList: Codable {
let type: String
let values: [Value]
enum CodingKeys: String, CodingKey {
case type = "$type"
case values = "$values"
}
}
// MARK: - Value
struct Value: Codable {
let title, text:String // left only <<< access to Title and Text
enum CodingKeys: String, CodingKey {
case title = "Title"
case text = "Text"
}
}
Do I have to make a struct and let for everything? Even for things I won't use, like $type, GroupName?
No only properties that you'll use
You could try this:
struct YourStructName: Codable {
var statusCode: Int
var errorId: Int
var type: String // Maybe make this an enum case
var response: Response
enum CodingKeys: String, CodingKey {
case statusCode = "StatusCode"
case errorId = "ErrorId"
case type = "$type"
case response = "ResponseList"
}
struct Response: Codable {
var type: String // Again, consider making this an enum case
var values: [ResponseValue]
enum CodingKeys: String, CodingKey {
case type = "$type"
case values = "$values"
}
struct ResponseValue: Codable {
var title: String
var text: String
enum CodingKeys: String, CodingKey {
case title = "Title"
case text = "Text"
}
}
}
}

How to convert a json payload to a custom object?

We have a json payload:
{
"aps": {
"alert": {
"title": "Payload",
"body": "Lets map this thing"
},
},
"type": "alert",
"message": "This is a message",
}
The custom object has been created:
class PushNotificationDetail {
var title: String //operation
var body: String //message
var type: detailType
var message: String?
init(title: String, body: String, type: detailType, message: string?){
self.title = title
self.body = body
self.type = type
self.message = message
}
}
The problem is mapping it correctly to the created object, what would be the best way to achieve this?
You should use Swift4 Codable protocol to initialise your object from the json returned by the api. You will need to restructure your structure to match the data returned by the api:
struct PushNotificationDetail: Codable, CustomStringConvertible {
let aps: Aps
let type: String
let message: String?
var description: String { return aps.description + " - Type: " + type + " - Message: " + (message ?? "") }
}
struct Aps: Codable, CustomStringConvertible {
let alert: Alert
var description: String { return alert.description }
}
struct Alert: Codable, CustomStringConvertible {
let title: String
let body: String
var description: String { return "Tile: " + title + " - " + "Body: " + body }
}
extension Data {
var string: String { return String(data: self, encoding: .utf8) ?? "" }
}
Playground Testing
let json = """
{"aps":{"alert":{"title":"Payload","body":"Lets map this thing"}},"type":"alert","message":"This is a message"}
"""
if let pnd = try? JSONDecoder().decode(PushNotificationDetail.self, from: Data(json.utf8)) {
print(pnd) // "Tile: Payload - Body: Lets map this thing - Type: alert - Message: This is a message\n"
// lets encode it
if let data = try? JSONEncoder().encode(pnd) {
print(data.string) // "{"aps":{"alert":{"title":"Payload","body":"Lets map this thing"}},"type":"alert","message":"This is a message"}\n"
print(data == Data(json.utf8)) // true
}
}
You can do this with a failable initialiser in your PushNotificationDetail class and a chained guard statement:
init?(jsonDict: [String : Any]) {
guard let typeString : String = jsonDict[“type”] as? String,
let message: String = jsonDict[“message”] as? String,
let aps : [String : Any] = jsonDict[“aps”] as? [String : Any],
let alert : [String : String] = aps[“alert”] as? [String : String],
let title : String = alert[“title”],
let body : String = alert[“body”] else { return nil }
// implement some code here to create type from typeString
self.init(title: title, body: body, type: type, message: message)
}
Hope that helps.